String formatting and namedtuple

I've been experimenting with namedtuple, it seems that string formatting doesn't recognize namedtuple as mapping. from collections import namedtuple Nt = namedtuple('Nt', ['x', 'y']) nt = Nt(12, 32) print 'one = %(x)s, two = %(y)s' % nt # output should be: one = 12, two = 32 currently, it is possible to use nt._asdict() as a workaround, but I think it will be easier and more intuitive to be able to use namedtuple directly with string interpolation Sorry, if this issue has been discussed before.

On Tue, Feb 10, 2009, Lie Ryan wrote:
This makes perfect sense to me; I think you should feel free to go ahead and submit a patch. (Regardless of whether the patch gets accepted, at least we would have a good record -- python-ideas is not really a good place to record ideas, and this is something nice and simple.) -- 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 Tue, Feb 10, 2009, Aahz wrote:
Actually, I just realized that this can't work because then you couldn't have print 'one = %s, two = %s' % nt due to the overloading on __getitem__(). Even if you could somehow special-case this, tuple index sequencing needs to continue working as fast path. -- 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 Tue, Feb 10, 2009 at 3:43 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Exposing a dict API would pollute namedtuple. 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.) -- Adam Olsen, aka Rhamphoryncus

[Lie Ryan]
I've been experimenting with namedtuple, it seems that string formatting doesn't recognize namedtuple as mapping.
That's because a named tuple isn't a mapping ;-) It's a tuple that also supports getattr() style access.
This is not unique to named tuples. String interpolation and the string format do not use getattr() style access with any kind of object: print '<%(real)s, %(imag)s>' % (3+4j) # doesn't find real/imag attributes Raymond

On Wed, Feb 11, 2009 at 12:11 PM, Raymond Hettinger <python@rcn.com> wrote:
Hm... I see a feature request brewing. In some use cases it might make a *lot* of sense to have a variant of .format() that uses __getattr__ instead of __getitem__... -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Wed, Feb 11, 2009 at 3:53 PM, Guido van Rossum <guido@python.org> wrote:
Perhaps the feature request here should be that vars() be able to work on built-in types like these, so we could just use it as a simple wrapper.
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://techblog.ironfroggy.com/ Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy

On Wed, Feb 11, 2009 at 1:05 PM, Calvin Spealman <ironfroggy@gmail.com> wrote:
I don't think you need vars(). vars() is for discovery of *all* attributes, but .format() doesn't need that. An adaptor like this would do it, but it would be nice if there was a shorthand for something like this (untested) snippet: class GetItemToGetAttrAdaptor: def __init__(self, target): self.target = target def __getitem__(self, key): try: return getattr(self.target, key) except AttributeError as e: raise KeyError(str(e)) You could then use "re={real} im={imag}".format(GetItemToGetAttrAdaptor(1j+2)) -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Wed, Feb 11, 2009 at 4:10 PM, Guido van Rossum <guido@python.org> wrote:
What if non-__dict__-having objects were treated exactly like that by vars(), returning this adapter and providing a uniform interface? Note that it would not, especially when invoked via vars(), allow setitem->setattr mapping. -- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://techblog.ironfroggy.com/ Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy

On Wed, Feb 11, 2009 at 1:19 PM, Calvin Spealman <ironfroggy@gmail.com> wrote:
Having a __dict__ is not the deciding factor, it would be whether __getitem__ is defined. You could try try: val = x[key] except AttributeError: val = getattr(x, key) but I worry this is likely to mask bugs where one simply passed the wrong object. (Also I realize that my example .format(Adaptor(...)) doesn't work -- it would have to be .format(**Adaptor(...)).) -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Tue, Feb 10, 2009, Lie Ryan wrote:
This makes perfect sense to me; I think you should feel free to go ahead and submit a patch. (Regardless of whether the patch gets accepted, at least we would have a good record -- python-ideas is not really a good place to record ideas, and this is something nice and simple.) -- 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 Tue, Feb 10, 2009, Aahz wrote:
Actually, I just realized that this can't work because then you couldn't have print 'one = %s, two = %s' % nt due to the overloading on __getitem__(). Even if you could somehow special-case this, tuple index sequencing needs to continue working as fast path. -- 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 Tue, Feb 10, 2009 at 3:43 AM, Lie Ryan <lie.1296@gmail.com> wrote:
Exposing a dict API would pollute namedtuple. 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.) -- Adam Olsen, aka Rhamphoryncus

[Lie Ryan]
I've been experimenting with namedtuple, it seems that string formatting doesn't recognize namedtuple as mapping.
That's because a named tuple isn't a mapping ;-) It's a tuple that also supports getattr() style access.
This is not unique to named tuples. String interpolation and the string format do not use getattr() style access with any kind of object: print '<%(real)s, %(imag)s>' % (3+4j) # doesn't find real/imag attributes Raymond

On Wed, Feb 11, 2009 at 12:11 PM, Raymond Hettinger <python@rcn.com> wrote:
Hm... I see a feature request brewing. In some use cases it might make a *lot* of sense to have a variant of .format() that uses __getattr__ instead of __getitem__... -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Wed, Feb 11, 2009 at 3:53 PM, Guido van Rossum <guido@python.org> wrote:
Perhaps the feature request here should be that vars() be able to work on built-in types like these, so we could just use it as a simple wrapper.
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://techblog.ironfroggy.com/ Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy

On Wed, Feb 11, 2009 at 1:05 PM, Calvin Spealman <ironfroggy@gmail.com> wrote:
I don't think you need vars(). vars() is for discovery of *all* attributes, but .format() doesn't need that. An adaptor like this would do it, but it would be nice if there was a shorthand for something like this (untested) snippet: class GetItemToGetAttrAdaptor: def __init__(self, target): self.target = target def __getitem__(self, key): try: return getattr(self.target, key) except AttributeError as e: raise KeyError(str(e)) You could then use "re={real} im={imag}".format(GetItemToGetAttrAdaptor(1j+2)) -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Wed, Feb 11, 2009 at 4:10 PM, Guido van Rossum <guido@python.org> wrote:
What if non-__dict__-having objects were treated exactly like that by vars(), returning this adapter and providing a uniform interface? Note that it would not, especially when invoked via vars(), allow setitem->setattr mapping. -- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://techblog.ironfroggy.com/ Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy

On Wed, Feb 11, 2009 at 1:19 PM, Calvin Spealman <ironfroggy@gmail.com> wrote:
Having a __dict__ is not the deciding factor, it would be whether __getitem__ is defined. You could try try: val = x[key] except AttributeError: val = getattr(x, key) but I worry this is likely to mask bugs where one simply passed the wrong object. (Also I realize that my example .format(Adaptor(...)) doesn't work -- it would have to be .format(**Adaptor(...)).) -- --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (6)
-
Aahz
-
Adam Olsen
-
Calvin Spealman
-
Guido van Rossum
-
Lie Ryan
-
Raymond Hettinger