TomCho
TomCho

Reputation: 3507

Getting all attributes to appear on python's `__dict__` method

Please consider the following python example:

In [3]: class test(object):
   ...:     attribute='3'
   ...:     def __init__(self):
   ...:         self.other='4'
   ...:         

In [4]: b=test()

In [5]: b.attribute
Out[5]: '3'

In [6]: b.__dict__
Out[6]: {'other': '4'}

Why is it that __dict__ only shows the "other" attribute and not "atribute"?

And how do I get a dictionary with all the classe's attributes and values? That is, how do I get this?

{'other': '4', 'attribute': '3'}

And I mean by using __dict__ or by some other simple means.

PS: related to this question, but couldn't quite get a dict from there.

PS2: I'm not look for test.__dict__ or b.__class__.__dict__, I'm looking for something that can be used as

In [3]: class test(object):
   ...:     attribute='3'
   ...:     def __init__(self):
   ...:         self.other='4'
   ...:     def _print_atr(self):
   ...:         # This should print exactly {'other': '4', 'attribute': '3'}
   ...:         print(self.__all_atr__)

In [4]: b=test()

In [5]: b.attribute
Out[5]: '3'

In [6]: b.__dict__
Out[6]: {'other': '4'}

Cheers

Upvotes: 7

Views: 6302

Answers (3)

mgilson
mgilson

Reputation: 309821

b.__dict__ is only a mapping of attributes on b, not on b's class (notice that __init__ isn't there either). The attributes on b's class are on the class's __dict__.

>>> class test(object):
...   attribute = 1
...   def __init__(self):
...     self.other = 2
... 
>>> b = test()
>>> b.__dict__
{'other': 2}
>>> test.__dict__
dict_proxy({'__module__': '__main__', 'attribute': 1, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, '__init__': <function __init__ at 0x1030f72a8>})

If you want both, you can do something like:

d = dict(vars(type(b)))
d.update(vars(b))

(note that some prefer vars(b) to b.__dict__) Of course, this doesn't get subclasses ...

If you want subclasses, you'll need to walk the method resolution order...

d = {}
for cls in type(b).__mro__:
    d.update(vars(cls))
d.update(vars(b))

Upvotes: 3

Moses Koledoye
Moses Koledoye

Reputation: 78536

attribute is not an instance attribute but a class attribute (can be seen in the mappingproxy test.__dict__).

You can get attribute in the instance __dict__ if you update the value of attribute from the instance:

>>> b = test()
>>> b.__dict__
{'other': '4'}
>>> b.attribute
'3'
>>> b.attribute = 5
>>> b.__dict__
{'attribute': 5, 'other': '4'}

Or keep the original value with

>>> b.attribute  = b.__class__.attribute # may not be necessary

Or you could change the definition of the class and move attribute into one of the class methods and bind it to the instance via self.

Upvotes: 8

Jo&#227;o Marcos Gris
Jo&#227;o Marcos Gris

Reputation: 81

Try typing:

test.__dict__

And it shows a key with 'attribute'. This happens exactly because attribute is a class variable not an instance variable.

Upvotes: 1

Related Questions