I have the following class:
class TestClass(object):
def __init__(self, **kwargs):
for key, value in kwargs.items(): #items return list of dict
setattr(self, key, value)
Examplary use:
obj = MessageItem(**{"testkey1":"tval1", "tkey2":"tval2", "tkey3":"tval3"})
How can I iterate on this structure without knowing the names of the attributes? Python provides us with the built-in method __getattribute__
, but I still need to know the name of the requested attribute:
print(obj.__getattribute__("testkey1"))
The __dict__
attribute holds what you want.
The class has it:
>>> class Foo:
... def __init__(self, x):
... self.x = x
...
>>> Foo.__dict__
mappingproxy({'__module__': '__main__', '__init__': <function Foo.__init__ at
0x000001CC1821EEA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__':
<attribute '__weakref__' of 'Foo' objects>, '__doc__': None})
And any instance has it as well:
>>> f = Foo(2)
>>> f.__dict__
{'x': 2}
You should access this attribute through the vars
builtin function.
Calling vars(foo)
will return foo.__dict__
.
See this related post: Use __dict__
or vars()
?.
Documentation for vars
:
vars([object])
Return the
__dict__
attribute for a module, class, instance, or any other object with a__dict__
attribute.Objects such as modules and instances have an updateable
__dict__
attribute; however, other objects may have write restrictions on their__dict__
attributes (for example, classes use atypes.MappingProxyType
to prevent direct dictionary updates).Without an argument,
vars()
acts likelocals()
. Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.
In addition, I tried and wrote a decorator that might interest you.
This is a class decorator, that adds a initKwargs
to the class it decorates.
Besides, it wraps the __init__
method of that class as well, so as to have it append the kwargs
dictionary it receives to the class' initKwargs
attribute.
def class_wrapper(cls):
cls.initKwargs = []
f = cls.__init__
def wrapped_init(instance, **kwargs):
cls.initKwargs.append(kwargs)
return f(instance, **kwargs)
cls.__init__ = wrapped_init
return cls
@class_wrapper
class Foo:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
Demonstration:
>>> f1 = Foo()
>>> f2 = Foo(a=1, b=2)
>>> f3 = Foo(a=1, b=2, c=3, d=4)
>>> Foo.initKwargs
[{}, {'a': 1, 'b': 2}, {'a': 1, 'b': 2, 'c': 3, 'd': 4}]
I find this approach much cleaner that using vars
, because you know what you're accessing since you define it yourself.
It gives you more control on the class' behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With