Dear gentlemen. This discussion gave me the pleasure of watching two programmers clash head to head.
I got here a lot of knowledge that no book covers. Thank you Alan & Steve. Yehuda On Mon, Jan 4, 2016 at 7:00 PM, <[email protected]> wrote: > Send Tutor mailing list submissions to > [email protected] > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.python.org/mailman/listinfo/tutor > or, via email, send a message with subject or body 'help' to > [email protected] > > You can reach the person managing the list at > [email protected] > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Tutor digest..." > > > Today's Topics: > > 1. Re: To FORMAT or not to (Steven D'Aprano) > 2. Re: To FORMAT or not to (Steven D'Aprano) > 3. Re: To FORMAT or not to (Steven D'Aprano) > 4. Re: To FORMAT or not to (Alan Gauld) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Mon, 4 Jan 2016 12:13:13 +1100 > From: Steven D'Aprano <[email protected]> > To: [email protected] > Subject: Re: [Tutor] To FORMAT or not to > Message-ID: <[email protected]> > Content-Type: text/plain; charset=us-ascii > > On Sun, Jan 03, 2016 at 02:27:01PM +0200, yehudak . wrote: > > Hi there, > > In a program I wrote the following line (Python 3.5): > > > > print("You've visited", island, '&', new + ".") > > > > A programmer told me that it's a bad habit, and I should have used > instead: > > > > print("You've visited {0} {1} {2}{3}".format(island, "&", new, ".")) > > > > May I understand why? > > > This is nonsense. There is nothing wrong with using print they way you > did. > > print is designed to solve simple problems, and you had a simple > problem. format is designed to solve complicated problems. You can use > format, or % string interpolation, to solve simple problems too, but why > bother? These four lines all do more or less the same thing: > > > print("You've visited", island, '&', new + ".") > print("You've visited {0} {1} {2}{3}".format(island, "&", new, ".")) > print("You've visited {} & {}.".format(island, new)) > print("You've visited %s & %s." % (island, new)) > > > The second version is the LEAST sensible, it should be re-written as the > third version. But apart from that minor difference, there's no > practical difference between those lines. It is entirely a matter of > personal taste which you use. > > This doesn't mean that similar problems will also be a matter of > personal taste. As the problem gets more complex, one or the other gets > more appropriate. But there's nothing wrong with what you wrote. > > > > -- > Steve > > > ------------------------------ > > Message: 2 > Date: Mon, 4 Jan 2016 13:03:22 +1100 > From: Steven D'Aprano <[email protected]> > To: [email protected] > Subject: Re: [Tutor] To FORMAT or not to > Message-ID: <[email protected]> > Content-Type: text/plain; charset=utf-8 > > On Sun, Jan 03, 2016 at 02:04:22PM +0100, Chris Warrick wrote: > > > Here are a couple of reasons: > > * String formatting works everywhere, but this syntax is specific to > > print() ? if you use something else, you might end up producing faulty > > code > > That argument doesn't make sense to me. I think you mean semantics, > not syntax, as print uses the same syntax as all Python functions. But > the same might be said about EVERY function and method. > > I might say, "Don't use format, because the semantics is specific to > format -- if you use something else, you might end up producting faulty > code". Well duh, of course it would, but if I used something else, I > wouldn't give it arguments that format requires. The same applies to > print, and literally every single other function and method. > > > > * The corrected string formatting usage is more readable than the > > original print() > > That's a matter of opinion, and not one that I share. > > > > * String concatenation with + requires that all arguments are strings, > > which is even less readable > > Again, that's a matter of opinion, and it's not a very credible opinion. > You're arguing that using a complex mini-language with mysterious pairs > of braces plus a method call: > > print("blah blah blah {}.".format(s)) > > is more readable than a simple concatenation: > > print("blah blah blah", s + ".") > > > I think not. > > > > * With string formatting, you can apply special formatting to your > > inputs (eg. set width, number precision?), which is hard or impossible > > with print() > > *shrug* > > Nobody says that format isn't capable of more advanced formatting > control than print. That's format's purpose, after all, just as print's > purpose is to print. But for the example given, when the formatting > needed is trivial and well within the capabilities of print, there's no > need to involve format. > > The SpaceX "Falcon" rocket will take you to space, and a skate-board > will take you around the block. If you strap a Falcon rocket to a > skate-board, and lay it on the ground, you can also use a Falcon to go > around the block. But why would you bother? > > > * Using print() with commas adds spaces between all entries, which > > might look bad (and it does in this example); > > Say what? Adding spaces between the entries is exactly what is needed > here, and it looks fine: > > py> island = "Mothering Sunday Island" > py> new = "cuddled a tree-climbing octopus" > py> print("You've visited", island, '&', new + ".") > You've visited Mothering Sunday Island & cuddled a tree-climbing octopus. > > > > the only way to prevent > > that is by setting `sep=`, but then you need to remember about a space > > after "visited" and around the ampersand? > > What? This argument makes no sense. There's no need to set sep='', the > example works fine with the default single space separator. > > > > > * Easy to localize (translate into different languages), which is > > generally impossible with any of the other options (some languages > > might rearrange the sentence!) > > A translation engine might use format internally for *part* of the job, > but the usual way to handle localisations is to call a function > (conventionally named underscore) to do the work. That *might* involve > using a template designed for format: > > _("You've visited {} & {}.", island, new) > > but could just as likely involve % or $ placeholders. That will allow > both the template and the terms to be localised. In any case, it is not > likely to involve a direct call to format for exactly the same reason > that it isn't likely to involve a direct use of print's simple format > control: it is too simple. > > Not only can word-order change, but a single word that gets injected > into one place of the template in Language A might end up being two > terms that are injected into two widely-separated places in Language B: > > # Language A > "blah blah blah blah {0} blah {1} blah blah", a, b > > # Language B > "blah blah {1} blah blah blah {0} blah blah {2} blah blah", a, b, c > > (and, by the way, the punctuation needs to be localised too). The > localisation engine can deal with that complexity. Trying to manage > translations yourself using just format cannot (or at least not easily). > > But fundamentally, the problem with this argument is YAGNI ("You Aren't > Going To Need It"). Don't over-engineer a simple script just in case > someday you will need to localize it for arbitrary languages. You won't. > And if you do, *that* is the time to rewrite the print call to include a > localisation step, not now. > > > > -- > Steve > > > ------------------------------ > > Message: 3 > Date: Mon, 4 Jan 2016 14:46:35 +1100 > From: Steven D'Aprano <[email protected]> > To: [email protected] > Subject: Re: [Tutor] To FORMAT or not to > Message-ID: <[email protected]> > Content-Type: text/plain; charset=us-ascii > > On Sun, Jan 03, 2016 at 01:12:41PM +0000, Alan Gauld wrote: > > > Why is it better? > > 1) It is slightly more performant. > > Consider that format has to build the entire output as a new string in > advance: > > "You've visited {0} & {2}.".format(island, new) > > gets generated before being passed to print for printing: > > print( result of above ) > > That involves copying each substring and building a single new string. > Imagine if island and new were each 100MB long texts, you would end up > with a third string, 200MB (plus a bit) in size, before print gets > called. But by calling print directly, it can write each substring (and > separator) to stdout one at a time, without needing to build up the > entire output first. > > But even for small strings, it has to parse the template, work out where > the braces are, determine how big the new string will be, allocate that > much memory (possibly causing a garbage collection pause), and copy the > arguments into the new string. > > I'm not so sure that all this will be faster than the simple-minded > actions of print: > > for each argument: > send str(argument) to stdout; > if this is not the last argument, send the separator > > Arguing that format+print is more efficient than print on its own seems > rather unlikely to be correct. > > > > 2) It improves consistency. You can store the format > > string as a variable and then print it out many times > > from different parts of your code and it will always > > be the same. This makes it much easier to maintain > > your program. For example: > > > > fmtString = "You've visited {0} & {2}." > > if foo: > > print(fmtString.format(foo,bar)) > > else: > > print(fmtString.format(baz,bad)) > > I wouldn't write it like that. I'd write: > > > if foo: > args = (foo, bar) > else: > args = (baz, bad) > print("You've visited {} & {}.".format(*args)) > > > but now we're out of the realm of simple uses like the Original Poster's > code. The original example gives us no reason to believe that we need to > conditionally change the values being printed, or print it more than > once. > > There's nothing wrong with using format. But for something as simple as > this example, you can equally use % or just call print directly. It > isn't an accident that print comes with its own basic formatting > control, it is a deliberate design choice. There's no *need* to > over-complicate the situation and then invent some spurious > justification for it: > > "format will save 0.000001 second of time!" > > "Maybe some day I'll need to translate this into Klingon!" > > "Perhaps I will decide to print the same string from ten different > places in the code!" > > Well, sure, but right now, there's no reason to think that one > microsecond will make any noticable difference, or that the program > needs to include translation, or print the string more than once. > > I think that, in this specific example, the only really good argument > for using format is a matter of taste: "I prefer to use format, because > I like it. It's more capable, so I use it more often and I am > comfortable and happy using it. There's no strong argument *against* > using it, so I prefer to use it." > > Great, that's fair, can't argue with that. There's no need to invent > justifications for format, or to say that format would be better in > *some other situation*. (We don't have some other situation, we have > this situation.) And if you disagree and prefer to just use print, > that's fine too. > > > -- > Steve > > > ------------------------------ > > Message: 4 > Date: Mon, 4 Jan 2016 10:04:41 +0000 > From: Alan Gauld <[email protected]> > To: [email protected] > Subject: Re: [Tutor] To FORMAT or not to > Message-ID: <[email protected]> > Content-Type: text/plain; charset=utf-8 > > On 04/01/16 03:46, Steven D'Aprano wrote: > > >> fmtString = "You've visited {0} & {2}." > >> if foo: > >> print(fmtString.format(foo,bar)) > >> else: > >> print(fmtString.format(baz,bad)) > > > > I wouldn't write it like that. I'd write: > > > > if foo: > > args = (foo, bar) > > else: > > args = (baz, bad) > > print("You've visited {} & {}.".format(*args)) > > In this case yes but the point I was trying to illustrate > was that you often want to print the same message from > several different places in your code - even in different > functions for example. Using a format string helps keep > that consistent. The if/else construct was just the most > concise example I could think of. > > > but now we're out of the realm of simple uses like the Original Poster's > > code. > > Indeed, and I did point that out at the start of my message. > Apart from one string addition the OPs use of print was > pretty seamless. But he wanted to know why the other > programmer thought formatting was better, not whether we thought > formatting was better in his particular case. At least that's > how I read it. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > > > ------------------------------ > > Subject: Digest Footer > > _______________________________________________ > Tutor maillist - [email protected] > https://mail.python.org/mailman/listinfo/tutor > > > ------------------------------ > > End of Tutor Digest, Vol 143, Issue 6 > ************************************* > _______________________________________________ Tutor maillist - [email protected] To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
