7 ms·
A good reference. My take home is that every single version that is possible to do in old style formatting is longer in new style formatting. Even more so if t
by sago 12y ago
A good reference.
My take home is that every single version that is possible to do in old style formatting is longer in new style formatting. Even more so if the old-style formatting were written without the extraneous 1-ples.
'%4d' % 42
vs
'{:4d}'.format(42)
It isn't surprising that so much code is still being written in old-style. The advantages of the new style, like padding with arbitrary characters; value reuse (particularly for I18n, though that tends to use a different mechanism for production systems that need it); and nested display; are really quite minor.
This feeds into the other python issue on HN today - why does py3 have so little uptake? Because it is a solution to a problem few people have.
- aidos 12y agoI had to read your statement a couple of times to understand it. You're saying that the old syntax is totally incompatible with the new syntax? It's a shame, but I'm sure it was necessary. The various other improvements are all things I've made use of in real code. Format is now a tool that you can reach for before you need to go to a more heavyweight templating lib (like Jinja2). '{p.type}: {p.kinds[0][name]}'.format(p=Plant())
- amelius 12y agoI think the following makes more sense: '{}'.format(format_decimal_with_prepended_spaces(42, 4))
- hobarrera 12y agoThis approach makes it really hard to change the formatting template. I might have several, which change at runtime (or even user-configurable). With this approach, my own app needs to do the actually formatting, while `format()` merely concats.
- mixmastamyk 12y agoYes, very nice, helpful site. .format() is mostly too verbose for my tastes. Even Guido himself put it into the "meh" category in a talk. To be clear, I do use it when I need quick lightweight templating, say building a very complicated string. But for most simple output printf style is shorter, simpler and I know it by heart. There was a guy at work who insisted on using .format() for everything that soured me on it, sometimes even simple string concatenation: print 'result: {long_var_name}'.format({long_var_name=long_var_name}) Sometimes lines reached 200 chars. If lines were broken down, they might extend to 4 lines for each debug statement, adding tons of clutter. Said it was more readable because you could ignore the end. :/ As sago said, printf is more concise in the majority of use cases. Not to mention the logging niceties: log.info('result: %s %s', one, two) # shorter and note that fmt is deferred! A _big_ one in my eyes. Too bad logging doesn't support {} internally. I've also wondered if .format could be improved if the % operator could be used with it, given appropriate precedence rules. Or perhaps use another char... dunno & or /? print 'results: {} {}' % results print 'results: {} {}' %% results print 'results: {} {}' / results Pycon, are you listening? ;)
- dalke 12y agoThis is what your co-worker does now: 'result: {long_var_name}'.format(long_var_name=long_var_name) A similar option is possible with '%'-style formatting: 'result: %(long_var_name)s'%{"long_var_name":long_var_name} -or- 'result: %(long_var_name)s'%dict(long_var_name=long_var_name) The first of these alternatives is indeed shorter, so long as there's only a single parameter. If there are multiple parameters then the .format() solution will be shorter. My experience with '%(name)s' % dict formatting is that I would often forget the terminal 's', and write it as '%(name)'. For template-like strings, where I want named substitutions, I am very much in favor of {}-style formatting. So if your co-worker insists on named substitutions, then s.format() is less verbose than s % dict. Regarding logging, there's a section of how to use format templates in the logging system, at https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles https://docs.python.org/3/howto/logging-cookbook.html#format... . In addition to using a LogRecord factory, you could reduce the overhead in old-style logging to only an extra constructor calls: log.info(M('result: {} {}', one, two)) where M.__str__ forwards to str.format. Personally, I would like a way to pre-compile the format string: fmt = format_compile("result: {} {} {}") for result in results: print(fmt(*result)) because currently (in Python 3.3) "%d %d %d" is about 40% faster than "{} {} {}". EDIT: Never mind: It can be faster to interpolate the string each time than to call a constructor: % python3.3 -mtimeit 's="%s %s %s"' 's % (1, 3, 9)' 1000000 loops, best of 3: 0.36 usec per loop % python3.3 -mtimeit 'class Spam:pass' 'Spam()' 10000 loops, best of 3: 23.6 usec per loop I did not expect a factor of 65!
- zwegner 12y agoYour timeit calls in the edit need the -s parameter before the first statements, so they aren't executed on each loop iteration. The overhead is in creating the class, not the instances. $ python3 -mtimeit -s 's="%s %s %s"' 's % (1, 3, 9)' 1000000 loops, best of 3: 0.343 usec per loop $ python3 -mtimeit -s 'class Spam:pass' 'Spam()' 10000000 loops, best of 3: 0.106 usec per loop
- dalke 12y agoThanks! That's a big forehead smack on my side. The numbers are more in line with what I expected. Meaning it is possible to defer some of the time cost by using a single constructor rather than evaluating the string.
- Trumpet6 12y agoMost of the examples of the brevity of the old style seem to be quite unconcerned with actual formatting. Honestly I just do simple print "Hello: " + a when I'm not too picky, and use .format when I actually want a nice output; the time of the few extra chars in format is unimportant compared to the time it takes to choose good field widths for the first time anyway, and I find the old syntax more cryptic.
- userbinator 12y agoValue reuse/positional parameter references could've been added easily to the old-style formatting in the same way POSIX added them to C's printf(), using the $ specifier (although printf() unusually indices from 1, not 0): '%1$s %0$s' % ('one', 'two', ) Changing the padding character would probably not be too difficult either - just add the appropriate specifier to the formatting DSL; and I'm not so keen on supporting nested structures in the format string, as it seems to be going in the direction of allowing arbitrary expressions/Python code into a formatting DSL - one that I think shouldn't be more than a regular language.
- Grue3 12y agoI almost always use format because it looks nicer, hence more readable. Shorter is not always better. It is also mandatory in i10n strings because if there are more than 2 arguments, they might be in different order in another language.