properties and formatting with self.__dict__

Bengt Richter bokr at oz.net
Sat Feb 22 19:25:32 CET 2003


On Wed, 19 Feb 2003 08:14:52 -0600, "Mark McEahern" <mark at mceahern.com> wrote:

>I hope the following example is not too obtuse, but it shows something that
>I thought was surprising about properties.  Attempting to format a string
>(traceback follows, with code at the end of the message) with named
>parameters and expecting the property to show up naively via self.__dict__
>generates this error:
>
>  Traceback (most recent call last):
>    File "./junk.py", line 23, in ?
>      print p
>    File "./junk.py", line 19, in __repr__
>      return template % self.__dict__
>  KeyError: full_name
>
>I'm not asking for workarounds because there are many and they are obvious.
>I guess I'm wondering whether this is a likely stumbling block in the
>intersection of string formatting and the use of properties?
>
self.__dict__ is not looking in the right namespace, because
self.__dict__[name] is not the same as getattr(self, name),
which is what you need in order to access self.name and find
class variables and properties.

I'm not sure if you want to call accessing the right namespace
a "workaround" (obvious or not), but you can do it with a class
instance that acts like a dict for the attribute names, e.g.,
try the following (I added quotation marks and a closing '>'
to the template to make the output easier to see):

====< attrns.py >======================================
#!/usr/bin/env python

class AttrNS(object):
    def __init__(self, obj): self.obj = obj
    def __getitem__(self, key): return getattr(self.obj, key)
        
class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def get_full_name(self):
        return '%s %s' % (self.first_name, self.last_name)

    full_name = property(get_full_name)

    def __repr__(self):
        template = '<Person ' \
                   'first="%(first_name)s" ' \
                   'last="%(last_name)s" ' \
                   'full="%(full_name)s">'
        return template % AttrNS(self)  # not: self.__dict__

p = Person('mark', 'mceahern')

print p
=======================================================
output:

[10:33] C:\pywk\clp>attrns.py
<Person first="mark" last="mceahern" full="mark mceahern">

>Thanks,
>
>// mark
>
>#!/usr/bin/env python
>
>class Person(object):
>
>    def __init__(self, first_name, last_name):
>        self.first_name = first_name
>        self.last_name = last_name
>
>    def get_full_name(self):
>        return '%s %s' % (self.first_name, self.last_name)
>
>    full_name = property(get_full_name)
>
>    def __repr__(self):
>        template = '<Person ' \
>                   'first=%(first_name)s ' \
>                   'last=%(last_name)s ' \
>                   'full=%(full_name)s'
>        return template % self.__dict__
>
>p = Person('mark', 'mceahern')
>
>print p
>
>-

Regards,
Bengt Richter




More information about the Python-list mailing list