Getting a dictionary from an object

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Sun Jul 24 20:52:49 CEST 2005


Steven D'Aprano a écrit :
> On Sun, 24 Jul 2005 12:07:02 +0300, Thanos Tsouanas wrote:
>>
>>>Thanos Tsouanas wrote:
>>>
(snip)
>>I didn't know about it, but I knew about object.__dict__ which is, as I
>>see equivalent with vars(object).  But it doesn't do the job for me,
>>since it fails to grab all obj.foo's, some of them being properties,
>>etc.
> 
(snip)
 > I don't think you are correct. As far as I can see, properties do have
> an entry in obj.__dict__ the same as other attributes, although there is
> certainly some strangeness going on with properties.
> 
> Using the sample code from here:
> http://www.python.org/2.2.3/descrintro.html#property
> 
> class C(object):
>     def __init__(self):
>         self.__x = 0
>     def getx(self):
>         return self.__x
>     def setx(self, x):
>         if x < 0: x = 0
>         self.__x = x
>     x = property(getx, setx)
> 
> I see _C__x in C().__dict__, exactly as expected. (snip)

Yes, but you don't see 'x'.  Poking into the object's __dict__ would 
defeat the whole point of computed attributes - which by the way need 
not directly map to a protected or private variable, nor even be 
properties (think: descriptors).

> I can't see any way to inspect a Python object and get a list of
> properties, 

I do :

def list_properties(obj):
     proptype = type(property()) # not defined in types
     klass = obj.__class__
     names = dir(klass) # so we get inherited attribs as well
     d  = dict([(name, getattr(klass, name)) for name in names])
     return [name for name, attrib in d.items() \
             if type(attrib) is proptype]



Note that this won't find all descriptors (I've tried and it really 
harder... there are a lot of things in a class.__dict__ that have a 
__get__() method, most of'em not defined in the types module).

Anyway, you won't need it... (I mean, the OP don't need it to solve it's 
problem)

> so you might have to keep your own list: add a class-attribute
> of your object which keeps a list of all the properties:
> 
> class Obj:
>     # various methods, attributes and properties
>     ...
>     # keep a list of special properties that don't show 
>     # up correctly in __dict__
>     special = ['foo', 'bar']
> 
>     # now define a special method that makes a copy of 
>     # __dict__ and adds special properties to it
> 
>     def objdict(self):
>         D = self.__dict__.copy()
>         # assume shallow copy is enough
>         for property_name in self.special:
>             D[property_name] = self.__getattribute__(property_name)
>         return D
> 
> then call it when you need it:
> 
> print "My object has fields %(foo)s and %(bar)s." % obj.objdict()

This means adding responsabilities to the class when the need is 
obviously orthogonal to the class's responsabilities. Implementing a 
generic decorator pattern in Python does'nt require more code, doesn't 
requires the class nor the object to be modified at all, is probably 
more robust, and  is, well... more generic !-)  (should I say 'more 
pythonic' ?)

> It would be nice to see an easier way to introspect objects and get
> a list of properties.

You're dream is now reality. Now ain't *that* nice ?-)

Bruno



More information about the Python-list mailing list