[Baypiggies] A properties and obj.__dict__ question
Mark Voorhies
mvoorhie at yahoo.com
Fri Sep 9 06:23:19 CEST 2011
On Thursday, September 08, 2011 09:18:44 pm Mark Voorhies wrote:
> On Thursday, September 08, 2011 08:51:05 pm Glen Jarvis wrote:
> > I have a question that is hard to ask without involving code. I reduced my
> > project down to a tiny test case (as follows).
> >
> > As you see, the following code will work and access the variables within the
> > class successfully. However, it's a cheat, using the internal attributes
> > instead of the properties (as properties don't show in __dict__).
> >
> > The objective is to have a large string with different fields. The fields
> > happen to all be members of my class. So, I could hard code things like
> > this:
> >
> > message = """
> > Name: %s
> > Address: %s
> > %s, %s %s
> > """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
> >
> > But, as each of the items are properties of the class, I'd like to be more
> > dynamic, like this:
> >
> > message = """
> > Name: %(obj.name)s
> > Address: %(obj.address)s
> > %(obj.city)s, %(obj.state)s %(obj.postal_code)s
> > """ % obj
> >
> > I can do this with normal attributes, like the following:
> >
> > message = """
> > Name: %(name)s
> > Address: %(address)s
> > %(city)s, %(state)s %(postal_code)s
> > """ % obj.__dict__
> >
> > However, these attributes in my case are properties and don't show in the
> > __dict__.
> >
> > Here's a runnable piece of code to demonstrate:
> >
> >
> > =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
> > class Piggie(object):
> > def __init__(self):
> > """A demo for a BayPIGgies question"""
> > self._name = None
> > self._address = None
> >
> > @property
> > def name(self):
> > return self._name
> >
> > @name.setter
> > def name(self, value):
> > if isinstance(value, basestring):
> > value = value.strip()
> > self._name = value
> >
> > @property
> > def address(self):
> > return self._address
> >
> > @address.setter
> > def address(self, value):
> > if isinstance(value, basestring):
> > value = value.strip()
> > self._address = value
> >
> > def __unicode__(self):
> > if self.name is None:
> > return u"Nameless Person"
> > else:
> > return self.name
> > __str__ = __unicode__
> >
> >
> > f = Piggie()
> > f.name = 'Glen'
> >
> >
> > message = """
> > Obviously, this is silly for only two fields like this.
> >
> > But, it's a very reduced test case to demo a problem from a
> > much larger project.
> >
> > Name: %(_name)s
> > Address: %(_address)s
> > """ % f.__dict__
> >
> > print message
> > =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
> >
> >
> > This works, as the output below shows. However, only by accessing the
> > internal attributes of the class directly, not using the property accessors.
> > How can I do something like this, but with property accessors. Something
> > like dir(f) or f.__property_dict__ that just has the properties.
> >
> > Run:
> >
> >
> > Obviously, this is silly for only two fields like this.
> >
> > But, it's a very reduced test case to demo a problem from a
> > much larger project.
> >
> > Name: Glen
> > Address: None
> >
> >
> >
> > Run with the properties used:
> >
> > Traceback (most recent call last):
> > File "x.py", line 48, in <module>
> > """ % f.__dict__
> > KeyError: 'name'
> >
> >
> > Thanks, for letting me share :)
> >
> >
> >
> > Glen
> >
>
> What about:
>
> message = """
> Name: %(obj.name)s
> Address: %(obj.address)s
> %(obj.city)s, %(obj.state)s %(obj.postal_code)s
> """ % dict((i,getattr(obj,i)) for i in dir(obj))
>
> ?
>
> (obviously, this is dangerous if any attribute of obj has side effects)
>
> If this is a string to be modified at run time, would it be reasonable
> to just use eval or have the client supply an importable module?
> (i.e., if you want dynamic behavior, can you take advantage of the
> fact that Python is already a dynamic language?)
>
> --Mark
>
oops -- that code snippet should have been:
message = """
Name: %(name)s
Address: %(address)s
%(city)s, %(state)s %(postal_code)s
""" % dict((i,getattr(obj,i)) for i in dir(obj))
--Mark
More information about the Baypiggies
mailing list