Re: [Python-ideas] String formatting and namedtuple
On Wed, Feb 11, 2009 at 5:09 AM, Lie Ryan <lie.1296@gmail.com> wrote:
On Wed, Feb 11, 2009 at 7:41 PM, Adam Olsen <rhamph@gmail.com> wrote:
Exposing a dict API would pollute namedtuple.
What do you mean by "pollute namedtuple"?
I just mean that we don't want to add a bunch of extra options and features that'll only be appropriate for rare special cases.
What's more, it's unnecessary in python 2.6/3.0:
print('one = {0.x}, two = {0.y}'.format(nt)) one = 12, two = 32
(And before you ask, no, I don't think it's worth adding the dict API just to make old-style formatting a tiny bit easier.)
Is % interpolation deprecated? I've never heard of that...
There's no plans to remove it in the near future, so it's not deprecated, and there's no problem using it when it's convenient. However, .format() obsoletes it. .format() is significantly more powerful for reasons just like this. There's no reason to add new features to % interpolation with .format() around. -- Adam Olsen, aka Rhamphoryncus
On Wed, Feb 11, 2009 at 1:18 PM, Adam Olsen <rhamph@gmail.com> wrote:
On Wed, Feb 11, 2009 at 5:09 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Is % interpolation deprecated? I've never heard of that...
There's no plans to remove it in the near future, so it's not deprecated, and there's no problem using it when it's convenient.
However, .format() obsoletes it. .format() is significantly more powerful for reasons just like this. There's no reason to add new features to % interpolation with .format() around.
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this? -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Wed, Feb 11, 2009 at 2:24 PM, Guido van Rossum <guido@python.org> wrote:
On Wed, Feb 11, 2009 at 1:18 PM, Adam Olsen <rhamph@gmail.com> wrote:
On Wed, Feb 11, 2009 at 5:09 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Is % interpolation deprecated? I've never heard of that...
There's no plans to remove it in the near future, so it's not deprecated, and there's no problem using it when it's convenient.
However, .format() obsoletes it. .format() is significantly more powerful for reasons just like this. There's no reason to add new features to % interpolation with .format() around.
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
I'm going to hide behind my vague use of "near future". Although I didn't realize removal was even that specific yet. -- Adam Olsen, aka Rhamphoryncus
[Guido van Rossum]
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
I thought we had backed-off on this for a number of reasons. * waiting to see if users actually adopt and prefer the new way * no compelling reason to force people to convert right away * need a tool for automatic conversion (this may not be easy) * the code and api for the new-way hasn't had a chance to be shaken-out and battle-tested in real-world apps yet. both the api and implementation are not yet mature (i.e. how well does it work in templating apps and whatnot). Raymond
On Wed, Feb 11, 2009 at 1:44 PM, Raymond Hettinger <python@rcn.com> wrote:
[Guido van Rossum]
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
I thought we had backed-off on this for a number of reasons.
Can you refer me to a thread?
* waiting to see if users actually adopt and prefer the new way
Without deprecation as the stick I doubt that they will bother to even try it.
* no compelling reason to force people to convert right away
3.3 is not right away. :-)
* need a tool for automatic conversion (this may not be easy)
I believe we punted on this, otherwise we would have removed % from 3.0.
* the code and api for the new-way hasn't had a chance to be shaken-out and battle-tested in real-world apps yet. both the api and implementation are not yet mature (i.e. how well does it work in templating apps and whatnot).
Fair enough. But again, 3.3 is a long time away.
Raymond
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Wed, Feb 11, 2009, Guido van Rossum wrote:
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
Well, I thought it had been reversed. If it's not reversed, I'll start campaigning to keep it. I think any decision to deprecate % should come *after* 3.x has had significant uptake among the broader community. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
On Wed, Feb 11, 2009 at 1:51 PM, Aahz <aahz@pythoncraft.com> wrote:
On Wed, Feb 11, 2009, Guido van Rossum wrote:
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
Well, I thought it had been reversed. If it's not reversed, I'll start campaigning to keep it. I think any decision to deprecate % should come *after* 3.x has had significant uptake among the broader community.
That probably means we'll still be supporting % 5 years from now. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Wed, Feb 11, 2009 at 2:58 PM, Guido van Rossum <guido@python.org> wrote:
On Wed, Feb 11, 2009 at 1:51 PM, Aahz <aahz@pythoncraft.com> wrote:
On Wed, Feb 11, 2009, Guido van Rossum wrote:
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
Well, I thought it had been reversed. If it's not reversed, I'll start campaigning to keep it. I think any decision to deprecate % should come *after* 3.x has had significant uptake among the broader community.
That probably means we'll still be supporting % 5 years from now.
My concern is not so much with general users but rather projects attempting to support many versions at once. I know 3.0 tries to be a big jump, but I much prefer an incremental transition with as much overlap as we can stomach. I'd suggest waiting until we stop releasing 2.x before removing any more features. Of course that assumes 2.x won't stretch out into 10 years. -- Adam Olsen, aka Rhamphoryncus
Guido van Rossum wrote:
On Wed, Feb 11, 2009 at 1:18 PM, Adam Olsen <rhamph@gmail.com> wrote:
On Wed, Feb 11, 2009 at 5:09 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Is % interpolation deprecated? I've never heard of that... There's no plans to remove it in the near future, so it's not deprecated, and there's no problem using it when it's convenient.
However, .format() obsoletes it. .format() is significantly more powerful for reasons just like this. There's no reason to add new features to % interpolation with .format() around.
I agree.
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
I am aware of this as your idea and possibly even as your 'plan', but not of it as a consensus plan. I sense that there may be some quiet opposition. There is certainly some disconnect on the issue. So, unless you intend a quick BDFL pronouncement, I recommend you sometime start a "Deprecate % interpolation" thread to get arguments pro and con exposed and argued. tjr
[Terry Reedy]
There is certainly some disconnect on the issue.
FWIW, whenever I done talks on 3.0, it is common to get an aversive reaction when the new syntax is shown. I pitch it in a positive light, but you can sense churning stomachs.
get arguments pro and con exposed and argued.
One risk is that maintainers of third-party modules may be disincentivized from converting to 3.x. For heavy users of %-formatting, it may be easiest just to stay in the 2.x world (unless an automated conversion tool emerges). Another thought is that it is premature to mandate that others convert until we ourselves have updated the standard library. That exercise may be informative and provide some evidence about how easy, how hard, or how possible it is to convert. Also, conversion may be difficult in cases where the existing syntax has been exposed to end-users and is a guaranteed part of the API (perhaps in config files, templates, file renamers, mail mergers, etc.) In our own code, logging formatters spring to mind. Raymond
On Wed, Feb 11, 2009, Raymond Hettinger wrote:
Also, conversion may be difficult in cases where the existing syntax has been exposed to end-users and is a guaranteed part of the API (perhaps in config files, templates, file renamers, mail mergers, etc.) In our own code, logging formatters spring to mind.
My previous company exposed raw Python code to end-users, so this it not a trivial concern. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
On Wed, Feb 11, 2009 at 2:15 PM, Terry Reedy <tjreedy@udel.edu> wrote:
Guido van Rossum wrote:
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
I am aware of this as your idea and possibly even as your 'plan', but not of it as a consensus plan. I sense that there may be some quiet opposition.
It's not quiet any more.
There is certainly some disconnect on the issue.
So, unless you intend a quick BDFL pronouncement, I recommend you sometime start a "Deprecate % interpolation" thread to get arguments pro and con exposed and argued.
I don't intend to force the issue. I'm disappointed though -- .format() fixes several common stumbling blocks with %(name)s and at least one with %s. Let someone else start a new thread. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
I am combining responses to several posts. Guido van Rossum wrote:
[Raymond] I thought we had backed-off on this for a number of reasons.
Can you refer me to a thread?
I believe there was one over a year ago on backing off from deprecation in 3.0. I also believe the alternative time frame was subject to differential interpretation. ***
That probably means we'll still be supporting % 5 years from now.
Declare % interpolation 'frozen': no new features. [As Raymond suggested with respect to attribute lookup.] ***
Without deprecation as the stick I doubt that they will bother to even try it. ... .format() fixes several common stumbling blocks with %(name)s and at least one with %s.
If there is a concise article on "Advantages of .format over % interpolation" to encourage use of the former, I am not aware of it. Attribute lookup with field.name is one of many to promote. One thing probably not mentioned in the PEP is the possibility of bound methods, reduces typing of '.format' for reused formats.
msg = "{0} == {1}".format print(msg('.format', 'improvement')) .format == improvement msg('Python', 'greatness') 'Python == greatness'
[Steven D'Aprano]
It's great for complex tasks, but it's hard to beat % for simple ones.
This seems to be a common feeling. PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to the new scheme! Terry Jan Reedy
Le Wed, 11 Feb 2009 20:06:37 -0500, Terry Reedy <tjreedy@udel.edu> a Ă©crit :
One thing probably not mentioned in the PEP is the possibility of bound methods, reduces typing of '.format' for reused formats.
msg = "{0} == {1}".format print(msg('.format', 'improvement')) .format == improvement msg('Python', 'greatness') 'Python == greatness'
This is relevant. I've read the PEP and was not aware of such a wide open door. It allows building collections of string formats. Why not makes them public? Why not e.g. start a wiki page for common useful formats? Why not then store them into a standard module? I see loads of uses in the sole field of UI. "Please, enter a {0}." "Hello, {0}! Ausgeschlafen? Press enter to continue..." (slept well?) "name: {0} -- phone:{1} -- email{2}" Denis ------ la vida e estranya
Can't roughly the same thing be achieved with % substitution?
msg = '%s == %s' print(msg % ('.format', 'improvement')) .format == improvement msg % ('Python', 'greatness') 'Python == greatness'
The main non-syntactic difference here is that msg is a normal string object rather than a bound method. Not arguing against moving to .format, just that it doesn't seem inherently more powerful than % in this case. (I guess you could still argue that this pattern alleviates a concern with .format, namely repeated typing of .format, but that's never been an issue with % to begin with.) On Thu, Feb 12, 2009 at 05:10, spir <denis.spir@free.fr> wrote:
Le Wed, 11 Feb 2009 20:06:37 -0500, Terry Reedy <tjreedy@udel.edu> a Ă©crit :
One thing probably not mentioned in the PEP is the possibility of bound methods, reduces typing of '.format' for reused formats.
msg = "{0} == {1}".format print(msg('.format', 'improvement')) .format == improvement msg('Python', 'greatness') 'Python == greatness'
This is relevant. I've read the PEP and was not aware of such a wide open door. It allows building collections of string formats. Why not makes them public? Why not e.g. start a wiki page for common useful formats? Why not then store them into a standard module?
I see loads of uses in the sole field of UI. "Please, enter a {0}." "Hello, {0}! Ausgeschlafen? Press enter to continue..." (slept well?) "name: {0} -- phone:{1} -- email{2}"
Denis ------ la vida e estranya _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- It is better to be quotable than to be honest. -Tom Stoppard Borowitz
On Thu, Feb 12, 2009 at 10:29 AM, David Borowitz <ddborowitz@gmail.com> wrote:
Can't roughly the same thing be achieved with % substitution?
msg = '%s == %s' print(msg % ('.format', 'improvement')) .format == improvement msg % ('Python', 'greatness') 'Python == greatness'
The main non-syntactic difference here is that msg is a normal string object rather than a bound method.
Not arguing against moving to .format, just that it doesn't seem inherently more powerful than % in this case. (I guess you could still argue that this pattern alleviates a concern with .format, namely repeated typing of .format, but that's never been an issue with % to begin with.)
It has the classic issue that % always has: if there's a single %s in the format string it will do the wrong thing when the argument is a tuple.
s = "[%s]" mystery_object = () s % mystery_object Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: not enough arguments for format string
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
On Thu, Feb 12, 2009 at 10:29 AM, David Borowitz <ddborowitz@gmail.com> wrote:
Can't roughly the same thing be achieved with % substitution?
msg = '%s == %s' print(msg % ('.format', 'improvement')) .format == improvement msg % ('Python', 'greatness') 'Python == greatness'
The main non-syntactic difference here is that msg is a normal string object rather than a bound method.
Not arguing against moving to .format, just that it doesn't seem inherently more powerful than % in this case. (I guess you could still argue that this pattern alleviates a concern with .format, namely repeated typing of .format, but that's never been an issue with % to begin with.)
It has the classic issue that % always has: if there's a single %s in the format string it will do the wrong thing when the argument is a tuple.
s = "[%s]" mystery_object = () s % mystery_object Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: not enough arguments for format string
Using bound methods was, to me, a lesser point of my post. I still am curious what anyone thinks of PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format. Terry Jan Reedy
On Thu, Feb 12, 2009, Terry Reedy wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 -- given this, I would remove half my objection to .format(); the rest has mostly to do with backward compatibility as explained previously. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 -- given this, I would remove half my objection to .format(); the rest has mostly to do with backward compatibility as explained previously.
+1 from here also. Raymond
Raymond Hettinger wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 -- given this, I would remove half my objection to .format(); the rest has mostly to do with backward compatibility as explained previously.
+1 from here also.
http://bugs.python.org/issue5237 This idea was pulled to full consciousness by your comment that we should tweak .format(), based on use experience, before deprecating % interpolation. tjr
Aahz wrote:
On Thu, Feb 12, 2009, Terry Reedy wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 -- given this, I would remove half my objection to .format(); the rest has mostly to do with backward compatibility as explained previously.
+1 from me, too.
On Thu, Feb 12, 2009 at 2:24 PM, Terry Reedy <tjreedy@udel.edu> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
What happens when both empty and non-empty fields appear ? E.g. would 'I love {} with {1} and {} with {1}'.format('bacon', 'eggs', 'sausage') return 'I love bacon with eggs and eggs with eggs', or it would be smarter and see that 1 is used explicitly and skip over it, giving 'I love bacon with eggs and sausage with eggs' ? George
On Thu, Feb 12, 2009, George Sakkis wrote:
On Thu, Feb 12, 2009 at 2:24 PM, Terry Reedy <tjreedy@udel.edu> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
What happens when both empty and non-empty fields appear ? E.g. would
'I love {} with {1} and {} with {1}'.format('bacon', 'eggs', 'sausage')
return 'I love bacon with eggs and eggs with eggs', or it would be smarter and see that 1 is used explicitly and skip over it, giving 'I love bacon with eggs and sausage with eggs' ?
I'd favor raising an exception. Alternatively, we could do the equivalent of what % formatting does, which would be the first option (that is, '{#}' is considered equivalent to mapped interpolation in % formatting). -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
Aahz wrote:
On Thu, Feb 12, 2009, George Sakkis wrote:
On Thu, Feb 12, 2009 at 2:24 PM, Terry Reedy <tjreedy@udel.edu> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format. What happens when both empty and non-empty fields appear ? E.g. would
'I love {} with {1} and {} with {1}'.format('bacon', 'eggs', 'sausage')
return 'I love bacon with eggs and eggs with eggs', or it would be smarter and see that 1 is used explicitly and skip over it, giving 'I love bacon with eggs and sausage with eggs' ?
I'd favor raising an exception. Alternatively, we could do the equivalent of what % formatting does, which would be the first option (that is, '{#}' is considered equivalent to mapped interpolation in % formatting).
From http://bugs.python.org/issue5237 """This proposal is currently all or nothing for simplicity of description and presumed ease of implementation. The patch to the doc could then be "If all replacement fields are left blank, then sequential indexes 0,1, ... will be automatically inserted." inserted after [Each replacement field contains either the numeric index of a positional argument, or the name of a keyword argument.]. Mixing blank and non-blank specs would then be an error and raise an exception. """ I think mixing implicit and explicit indexes would be confusing. Mixing implicit indexes and keywords could perhaps work, but I won't propose that. It would be a rare usage, while my goal is to make the common case '%s' format as easy to write as it is now, by replacing '%s' with '{}' [two keystrokes each]. Terry Jan Reedy
Le Thu, 12 Feb 2009 23:29:33 -0500, Terry Reedy <tjreedy@udel.edu> a Ă©crit :
Aahz wrote:
On Thu, Feb 12, 2009, George Sakkis wrote:
On Thu, Feb 12, 2009 at 2:24 PM, Terry Reedy <tjreedy@udel.edu> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
> msg = "{} == {}".format Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format. What happens when both empty and non-empty fields appear ? E.g. would
'I love {} with {1} and {} with {1}'.format('bacon', 'eggs', 'sausage')
return 'I love bacon with eggs and eggs with eggs', or it would be smarter and see that 1 is used explicitly and skip over it, giving 'I love bacon with eggs and sausage with eggs' ?
I'd favor raising an exception. Alternatively, we could do the equivalent of what % formatting does, which would be the first option (that is, '{#}' is considered equivalent to mapped interpolation in % formatting).
From
http://bugs.python.org/issue5237
"""This proposal is currently all or nothing for simplicity of description and presumed ease of implementation. The patch to the doc could then be "If all replacement fields are left blank, then sequential indexes 0,1, ... will be automatically inserted." inserted after [Each replacement field contains either the numeric index of a positional argument, or the name of a keyword argument.]. Mixing blank and non-blank specs would then be an error and raise an exception. """
I think mixing implicit and explicit indexes would be confusing. Mixing implicit indexes and keywords could perhaps work, but I won't propose that. It would be a rare usage, while my goal is to make the common case '%s' format as easy to write as it is now, by replacing '%s' with '{}' [two keystrokes each].
Terry Jan Reedy
Agree with the base {} proposal. Not really with forbidding mixing: A side-advantage is that this principle is consistent with the tuple/dict opposition: tuple items are implicitely numbered. Note that this is even more analog to positional vs keyword function arguments. So that there is probably no need to forbid {} and {name} in the same format string, as long as names came after positionally identified sub-strings. We need instead a rule stating that empty {} come first and that names comply with the common identifier pattern, in order to avoid conflicts with implicit indexes. Denis ------ la vida e estranya
Terry Reedy wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 from me. Just to make it explicit: omitting field names will be an all-or-nothing proposition: you can't omit some of them unless you omit them all. Correct? -- Steven
Steven D'Aprano wrote:
Terry Reedy wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 from me. Just to make it explicit: omitting field names will be an all-or-nothing proposition: you can't omit some of them unless you omit them all. Correct?
That is my proposal. I should have made that clearer, as I now did on the tracker issue I filed. My idea was that the function could switch from current behavior to alternative behavior depending on the presence or absence of anything in the first {}. But that is up to the patch writer. tjr
Some reactions: First, let me say that PEP 3101 was always meant to be an expression of the python-dev consensus rather than the ideas of one specific person. So as far as I am concerned, the consensus rules. That being said, I can think of two objections to your proposal, although I don't feel strongly about either one. The first issue is that the character sequence '{}' isn't by itself suggestive of anything (except perhaps an empty dict.) The logical extrapolation from {ddd} to {} is a subtractive one, meaning that it only makes sense if you are starting from {ddd} to begin with. From a pedagogical perspective, I have a slight preference for language constructs that are naturally additive, meaning that I can teach the shortcut first and it makes intuitive sense. (However, there are lots of language features that violate that rule, which is why this argument is somewhat weak.) Secondly, there is an argument to be made towards moving away from any syntactical pattern that requires the programmer to synchronize two lists, in this case the set of '%' field markers in the string and the sequence of replacement values. Having to maintain a correspondence between lists is almost never a problem when code is first written, but I think we can all remember instances where bugs have been introduced by maintainers who added a new item to one list but forgot to add the corresponding item to the other list. More generally, I think that when you evaluate the goodness of either syntax, you should do so from the perspective of both the original code author as well as someone who is dealing with an existing code base that has undergone a large degree of churn. Thus, a case could be made that by forcing programmers to explicitly state the mapping between field marker and replacement value (either numerically, or preferably by name) that the code becomes a fraction more robust as a result. BTW, although the use of unbound methods is not mentioned in the PEP, I do recall discussions on the mailing list around that time that proposed a whole lot of different ways of wrapping format() to create various formatting APIs. Terry Reedy wrote:
Steven D'Aprano wrote:
Terry Reedy wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually. I think this is at least half the objection to switching to .format.
+1 from me. Just to make it explicit: omitting field names will be an all-or-nothing proposition: you can't omit some of them unless you omit them all. Correct?
That is my proposal. I should have made that clearer, as I now did on the tracker issue I filed. My idea was that the function could switch from current behavior to alternative behavior depending on the presence or absence of anything in the first {}. But that is up to the patch writer.
tjr
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
Le Thu, 12 Feb 2009 21:13:23 -0800, Talin <talin@acm.org> a Ă©crit :
Secondly, there is an argument to be made towards moving away from any syntactical pattern that requires the programmer to synchronize two lists, in this case the set of '%' field markers in the string and the sequence of replacement values. Having to maintain a correspondence between lists is almost never a problem when code is first written, but I think we can all remember instances where bugs have been introduced by maintainers who added a new item to one list but forgot to add the corresponding item to the other list.
I fully agree. But then the only solution is probably (re)considering a format ala Cobra: print 'Hello. My name is [name] and I am [age].' [] pairs can actually hold any valid expression: print "Found [count(n)*3+1] items." There were probably *very* good reasons to refuse such an obvious format. Denis ------ la vida e estranya
On Fri, Feb 13, 2009 at 10:20:19AM +0100, spir wrote:
print 'Hello. My name is [name] and I am [age].'
I found this exceptionally funny. print 'Hello. My name is {0} and I am {1}.' uses indexes where print 'Hello. My name is [name] and I am [age].' uses strings; time to talk about consistency with tuples/lists and dicts! <Big grin> Oleg. -- Oleg Broytmann http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
On Thu, Feb 12, 2009, Talin wrote:
Secondly, there is an argument to be made towards moving away from any syntactical pattern that requires the programmer to synchronize two lists, in this case the set of '%' field markers in the string and the sequence of replacement values. Having to maintain a correspondence between lists is almost never a problem when code is first written, but I think we can all remember instances where bugs have been introduced by maintainers who added a new item to one list but forgot to add the corresponding item to the other list.
This is still problematic with {#} syntax when lists are re-ordered, which creates a more difficult editing job. Moreover, precisely because {#} syntax doesn't blow up in the face of adding elements, it creates more silent bugs IMO. Altogether, although you have a point I think it ends up being the same total pain, just shifted around. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
On Thu, Feb 12, 2009 at 11:24 AM, Terry Reedy <tjreedy@udel.edu> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually.
Explicit syntax is better imho: "The answers are {.} and {.}.".format(x,y) I'm suggesting a bare dot because it looks like something rather than nothing and this syntax is currently invalid. --- Bruce
Bruce Leban wrote:
On Thu, Feb 12, 2009 at 11:24 AM, Terry Reedy <tjreedy@udel.edu <mailto:tjreedy@udel.edu>> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
> >> msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually.
Explicit syntax is better imho: "The answers are {.} and {.}.".format(x,y)
I'm suggesting a bare dot because it looks like something rather than nothing and this syntax is currently invalid.
-1 There is nothing 'explicit' about '.'. {} is just as currently invalid. The purpose of my proposal is to make the simple case simple. In terms of keystrokes, unshift - . - shift is as bad as unshift - 0 - shift. tjr
Terry Reedy wrote:
The purpose of my proposal is to make the simple case simple. In terms of keystrokes, unshift - . - shift is as bad as unshift - 0 - shift.
I have this mostly implemented in ''.format(), despite my earlier statement that I was done playing with it after the sample that's attached to http://bugs.python.org/issue5237. Now that I have this working in the core, I find Terry's argument above quite convincing. Not having to do the shift-unshift-shift dance to type in the format placeholder really does make it easier to use for the simple cases. I'm seeing this as a definite improvement.
Eric Smith wrote:
I have this mostly implemented in ''.format(), despite my earlier statement that I was done playing with it after the sample that's attached to http://bugs.python.org/issue5237.
The one issue that's causing me problems is what to do with format specifiers that themselves need expanding.
'{0:>{1}}'.format('foo', 5) ' foo'
Should:
'{:{}}'.format('foo', 5)
produce the same output, or should it be an error? I think it should probably work, but it complicates the implementation sufficiently that I probably won't be able to finish it up for a couple of weeks. I know this is a not-so-useful corner case, but the implementation has to do something here. I could easily throw an exception, but I don't see how that's more desirable than just making it work.
On 2/17/09, Eric Smith <eric@trueblade.com> wrote:
The one issue that's causing me problems is what to do with format specifiers that themselves need expanding.
'{0:>{1}}'.format('foo', 5) ' foo'
Should:
'{:{}}'.format('foo', 5)
produce the same output, or should it be an error? I think it should probably work, but it complicates the implementation sufficiently that I probably won't be able to finish it up for a couple of weeks.
I know this is a not-so-useful corner case, but the implementation has to do something here. I could easily throw an exception, but I don't see how that's more desirable than just making it work.
Then go ahead and throw an exception; it can always be made legal later. In 2.4, the original decorator patch applied to classes as well as functions. The restriction to only functions was made because the use case for classes wasn't as clear-cut, and it is much easier (from a policy standpoint) to add functionality than to take it away. (The restriction was removed in 2.6.) Those extra .format extensions would *probably* be useful, but there is little harm in waiting another month (or even another two releases) before adding them. -jJ
I've added a patch to http://bugs.python.org/issue5237 that implements the basic '{}' functionality in str.format. Read the note in the issue; this patch is not ready for production. But it will let you play with the feature. I like it, mainly because it's so much quicker to type '{}' than '{0}' because you don't have to shift-unshift-shift (on my US English keyboard). If we decide to add this feature I hope I can finish it before PyCon, or worst case finish it during the sprints.
Eric Smith wrote:
I've added a patch to http://bugs.python.org/issue5237 that implements the basic '{}' functionality in str.format.
I've added another patch to issue 5237 which I believe is production quality. I'll work on tests.
'{} {}'.format(1, 2) '1 2'
On Mon, Feb 16, 2009 at 11:59 AM, Terry Reedy <tjreedy@udel.edu> wrote:
Bruce Leban wrote:
On Thu, Feb 12, 2009 at 11:24 AM, Terry Reedy <tjreedy@udel.edu <mailto:tjreedy@udel.edu>> wrote:
PROPOSAL: Allow the simple case to stay simple. Allow field names to be omitted for all fields in a string and then default to 0, 1, ... so that example above could be written as
msg = "{} == {}".format
Given that computers are glorified counting machines, it *is* a bit annoying to be required to do the counting manually.
Explicit syntax is better imho: "The answers are {.} and {.}.".format(x,y)
I'm suggesting a bare dot because it looks like something rather than nothing and this syntax is currently invalid.
-1 There is nothing 'explicit' about '.'. {} is just as currently invalid. The purpose of my proposal is to make the simple case simple. In terms of keystrokes, unshift - . - shift is as bad as unshift - 0 - shift.
Well said. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum <guido@...> writes:
I don't intend to force the issue. I'm disappointed though -- .format() fixes several common stumbling blocks with %(name)s and at least one with %s.
Everytime I try to experiment a bit with format codes, I find them unintuitively complex:
"{0!r}".format(2.5) '2.5' "{0:r}".format(2.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Unknown conversion type r "{0!f}".format(2.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Unknown conversion specifier f "{0:f}".format(2.5) '2.500000'
Why must the 'f' code be preceded by a colon rather than by an exclamation mark? There is surely a rational explanation, but in day-to-day use it is really confusing. Add to this the annoyance of typing ".format" and of adding curly braces everywhere, and "%" is clearly handier despite the lonely tuple problem. Regards Antoine.
On Fri, Feb 13, 2009 at 6:19 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Guido van Rossum <guido@...> writes:
I don't intend to force the issue. I'm disappointed though -- .format() fixes several common stumbling blocks with %(name)s and at least one with %s.
Everytime I try to experiment a bit with format codes, I find them unintuitively complex:
"{0!r}".format(2.5) '2.5' "{0:r}".format(2.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Unknown conversion type r "{0!f}".format(2.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Unknown conversion specifier f "{0:f}".format(2.5) '2.500000'
Why must the 'f' code be preceded by a colon rather than by an exclamation mark?
Actually, !r is the exception. The rule is that a colon is followed by a formatting language specific to type type, e.g. {:f} (which is only supported by floating point numbers and means fixed-point), whereas an exclamation point is followed by a single letter that bypasses the type-specific formatting -- {!r} is really the only one you need to learn.
There is surely a rational explanation, but in day-to-day use it is really confusing. Add to this the annoyance of typing ".format" and of adding curly braces everywhere, and "%" is clearly handier despite the lonely tuple problem.
It is true that the advantages of .format() are probably more appreciated when you are writing a larger program. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
It is true that the advantages of .format() are probably more appreciated when you are writing a larger program.
True. I think that the auto-number feature goes a little way in helping replace casual uses of %-formatting. To that end, I've implemented a string.Formatter subclass that mostly implements this suggestion, just so people can try it out if they want. I believe it's complete, except it doesn't handle escaping '{' and '}'. It's attached to http://bugs.python.org/issue5237 as auto_number_formatter_3.py. $ ./python Python 2.7a0 (trunk:69608, Feb 14 2009, 04:51:18) [GCC 4.1.2 20070626 (Red Hat 4.1.2-13)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
from auto_number_formatter_3 import formatter as _ _('{} {} {}').format(3, 'pi', 3.14) '3 pi 3.14'
It also lets you add in format specifiers, conversion specifiers, and object access. Once you use those, the improvement of leaving out the index numbers is less clear. I'll leave it for debate if this is useful. I think it probably is, if only because it's easier to explain the behavior: If you leave out the 'field name', a sequential number is added in front of the 'replacement string' (using PEP 3101 nomenclature).
_('{} {} {}').format(3, 'pi', 3.14) '3 pi 3.14' _('{:#b} {!r:^16} {.imag}').format(3, set([14,3]), 3j+1) '0b11 set([3, 14]) 3.0'
It also supports all of the regular ''.format() behavior, you just can't mix-and-match using field names and omitting them.
_('{foo:10}').format(foo='bar') 'bar ' _('{0} {}').format(1, 2) Traceback (most recent call last): ... <details omitted for clarity> ValueError: cannot mix and match auto indexing
As I said, pure-Python example doesn't handle escaping '{' and '}' (because the parsing is tedious and already implemented in the C version), but is otherwise complete. If the consensus is that this is useful, I'll implement it in ''.format(), otherwise I'm done with this issue. Eric. PS: Just as a plug, I should note this is the first use I've found for the under-appreciated string.Formatter.
Guido van Rossum wrote:
On Wed, Feb 11, 2009 at 1:18 PM, Adam Olsen <rhamph@gmail.com> wrote:
On Wed, Feb 11, 2009 at 5:09 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Is % interpolation deprecated? I've never heard of that... There's no plans to remove it in the near future, so it's not deprecated, and there's no problem using it when it's convenient.
However, .format() obsoletes it. .format() is significantly more powerful for reasons just like this. There's no reason to add new features to % interpolation with .format() around.
I thought the plan was to start deprecating % in 3.1 and remove it at some later release (maybe 3.3). Or did I miss a reversal on this?
Judging by responses on comp.lang.python deprecating % will make a lot of people deeply unhappy. Personally, my own feeling is that they're (mostly) just objecting to change, but they do make some good points. In a later post, Guido wrote: "Without deprecation as the stick I doubt that they will bother to even try [format]." I think you under-estimate just how much many programmers like to play with shiny new tools. I installed Python 2.6 specifically so I could try format. My conclusion is that it is a nice, powerful *heavyweight* solution for text formatting. It's great for complex tasks, but it's hard to beat % for simple ones. -- Steven
participants (17)
-
Aahz
-
Adam Olsen
-
Antoine Pitrou
-
Bruce Leban
-
David Borowitz
-
Eric Smith
-
George Sakkis
-
Greg Ewing
-
Guido van Rossum
-
Jim Jewett
-
Mathias Panzenböck
-
Oleg Broytmann
-
Raymond Hettinger
-
spir
-
Steven D'Aprano
-
Talin
-
Terry Reedy