4 ms·
Why change the excellent printf-style string formatting syntax to the vastly inferior slf4j-style? If I want simple concatenation, i use concatenation. If I wan
by strictfp 14y ago
Why change the excellent printf-style string formatting syntax to the vastly inferior slf4j-style? If I want simple concatenation, i use concatenation. If I want really complex formatting I write explicit code to do it. Printf style hits a sweet spot: it formats common datatypes to common presentation formats. Python 3 adds a formatting mini-language which looks more convoluted for simple tasks and unreadable for complex ones. Why change the syntax?
- jbarham 14y agoI'm in the same boat. It's an old joke that Java tried to kill off printf style formatting but had to bring it back because it's a really great idea: 1980: C printf("%10.2f", x); 1988: C++ cout << setw(10) << setprecision(2) << showpoint << x; 1996: Java java.text.NumberFormat formatter = java.text.NumberFormat.getNumberInstance(); formatter.setMinimumFractionDigits(2); formatter.setMaximumFractionDigits(2); String s = formatter.format(x); for (int i = s.length(); i < 10; i++) System.out.print(' '); System.out.print(s); 2004: Java System.out.printf("%10.2f", x); 2008: Scala and Groovy printf("%10.2f", x) (from http://www.horstmann.com http://www.horstmann.com) To complete the circle I'd add: 2009: Go fmt.Printf("%10.2f", x)
- ondrasej 14y agoI wouldn't argue against using a formatting string in general, but the printf style order-based formatting strings are really bad once you need to localize your app and have to support languages with different word order. In this sense, .NET or Python3-like formatting strings with position-based formatting is orders of magnitude better and I was surprised that Sun decided to use %* instead. Take a simple example in the lines of "I've seen {0} {1} {2}".format("John", "eat", "an apple") ...and try localizing this message into e.g. German. I have a feeling that printf-style is one of the reasons, why the texts in localized versions of some programs are as bad as they are.
- DeepDuh 14y agoDo you really want to keep the same format strings when localizing an application? Isn't it much cleaner to just define multiple format strings? Translations in general don't work that way, you can't just move around words and translate them individually, usually the whole expression changes.
- psquid 14y agoThat's the point. You can't change the format strings to a different word order if the selection of values used to fill the fields is entirely dependent on word order (i.e., how the basic printf syntax works), unless you have a separate line/block of code that executes when the word order of the current locale differs.
- sausagefeet 14y agoWe just have a database of sentences and a translation is a lookup in the DB by some unique identifier. Trying to semi-translate a string just doesn't work very well in the long run (for us).
- DeepDuh 14y agoI see your point now. Yes, I can see Python 3's syntax facilitate some of that work. I still think you will need branches and/or polymorphisms to do more complex localizations, especially when you need to support east asian languages.
- Erwin 14y agoglibc sprintf supports that as something like %2$s %1$s which Python could potentially support. I don't buy the internationalization argument however. You have to explicitly select strings for i18n anyway and run them through something that retrieves the data from a catalogue based on the current language. It's not like you will override str.__mod__ to start i18n. And if you want to do it right, there are more complex rules that need a special formatting language. For example if you want to display {count} error/errors, then the text of error/errors will vary based on language not just based on count 0/1/more but even more wildly based on language. E.g. some have a special noun declension for 2. For example in Polish, that might be when there are 5 errors: http://blogs.transparent.com/polish/cardinal-numbers/ http://blogs.transparent.com/polish/cardinal-numbers/
- andrewaylett 14y agoPython supports `"%(name)s"`, which means you're not dependent on order at all -- in my opinion, much nicer than indexing into the parameter list: >>> "%(name)s has %(count)d %(thing)s" % {'thing': 'bananas', 'count': 10, 'name': "Phil"} 'Phil has 10 bananas'
- dalke 14y agoI found that I often (~1 time in 10) make a mistake with that syntax, and omit the trailing 's'. I think it's because I'm not used to having anything after a closing ')'.
- mturmon 14y agoSame problem here. Maybe the braces approach using {name} is an improvement upon %(name)s in that respect.
- andolanra 14y agoThe new-style formatting allows that as well: >>> "{name} has {count} {thing}".format( thing='bananas', count=10, name='Phil') 'Phil has 10 bananas' It also allows for more complex expressions inside of format specifiers, so if you need to grab data out of an object, you can do something like: >>> from collections import namedtuple >>> Sentence = namedtuple('Sentence', ['name', 'thing', 'count']) >>> s = Sentence(name='Phil', thing='bananas', count=10) >>> '{dat[0]} has {dat.count} {dat.thing}'.format(dat=s) 'Phil has 10 bananas' which is verbose and contrived here, but could be immensely useful in cases like >>> '... {numeral[5]} {item.plural}'.format( numeral=fr_numerals, item=animal) '... cinq animaux'
- vladev 14y ago2012: Python "{:10.2f}".format(x)
- paradoja 14y agoMhhh, don't know when: Haskell printf "%10.2f" x (Note the lack of parenthesis or commas)
- gvalkov 14y agoAs of Python 3.3.0a3, both printf and PEP 3101 [1] string formatting are still available, despite references to a possible deprecation of the '%' operator in the documentation [2]. I hope this is one of the areas where the cpython devs can turn a blind eye on the whole there should be preferably only one way to do it way of though. A few other PEP 3101 examples worth mentioning (and their printf equivalents): '{1} {0} and {2} {0}'.format('Wiggin', 'Andrew', 'Valentine') '%s, %s and %s' % tuple('%s Wiggin' % i for i in ('Andrew', 'Valentine')) >>> 'Andrew Wiggin and Valentine Wiggin' '{:<{w}} , {:<{w}} ,'.format('one', 'two', w=10) '%s , %s ,' % ('one'.ljust(10), 'two'.ljust(10)) >>> 'one , two ,' '{:^{w}} , {:^{w}} ,'.format('one', 'two', w=10) '%s , %s ,' % ('one'.center(10), 'two'.center(10) >>> ' one , two ,' # see object.__format__() [4] 'today is: {:%a %b %d}'.format(datetime.now()) 'today is: %s' % datetime.now().strftime('%a %b %d') >>> 'today is: Tue May 08' Imho, they really are quite flexible and allow for more elegant constructs when needed. Calling them 'vastly inferior' is unwarranted, especially since using them is not mandatory in any way. [1] http://www.python.org/dev/peps/pep-3101/ http://www.python.org/dev/peps/pep-3101/ [2] http://docs.python.org/release/3.0.1/whatsnew/3.0.html#changes-already-present-in-python-2-6 http://docs.python.org/release/3.0.1/whatsnew/3.0.html#chang... [3] http://docs.python.org/release/3.1.5/library/string.html#format-string-syntax http://docs.python.org/release/3.1.5/library/string.html#for... [4] http://docs.python.org/release/3.1.5/reference/datamodel.html#object.__format__ http://docs.python.org/release/3.1.5/reference/datamodel.htm...
- briancurtin 14y agoThe printf-style is really only deprecated in the sense that most of the core devs would prefer string.format. There's no formal deprecation policy in place to remove the printf-style. The standard library still uses printf-style, the documentation still uses printf-style, and printf-style isn't going away any time soon, if ever. Many core contributors have sided with printf-style and the community has spoken up a few times about wanting printf-style to stay around. I don't think we'll ever reach a majority siding with removal of it.
- raverbashing 14y agoPrintf format is great, but there's an issue You're repeating yourself. Why? Because C can't know what types you are passing to it. So you have to explicitly do '%d' or '%s' to let printf know what this is. But yes, I think it's easier to type than {0}
- eru 14y agoIn Python's old style you can use %s everywhere, and Python will figure out the types.