Adding Fields To A Class Via Setattr Vs. Storing A Dictionary In Python
Solution 1:
Looks fine to me, I would be tempted to re-write as:
classUser(object):def__init__(self, arg1, arg2, **traits):
self.arg1 = arg1
self.arg2 = arg2
self.traits = traits
If you really wanted, you could then override to fall back on the traits dictionary if an attribute can't be found:
def__getattr__(self, name):
returnself.traits[name]
Example:
>>> u = User(1, 2, email='something')
>>> y = User(1, 2, email='bob', telno='999')
>>> u.arg1, u.arg2, u.email
(1, 2, 'something')
>>> y.arg1, y.arg2, y.email, y.telno
(1, 2, 'bob', '999')
>>> y.arg1, y.arg2, y.email, y.something
Traceback (most recent call last):
File "<pyshell#105>", line 1, in <module>
y.arg1, y.arg2, y.email, y.something
File "/home/jon/adfafasdf.py", line 7, in __getattr__
return self.traits[name]
KeyError: 'something'
So you may wish to make that a more sensible error, and change to:
def__getattr__(self, name):
try:
return self.traits[name]
except KeyError as e:
raise AttributeError() # with suitably formatted string
Solution 2:
You can modify the instance's __dict__
directly (assuming that it doesn't implement __slots__
or anything silly like that)
Here's a simple example:
classTraits(object):
passclassUser(object):
def__init__(self,**traits):
self.traits = Traits()
self.traits.__dict__.update(traits)
a = User(eye_color="blue")
print a.traits.eye_color
Of course, it is probaby safer (but slightly less efficient) to just do:
class User(object):
def __init__(self,**traits):
self.traits = Traits()
for k,v in traits.items():
setattr(traits,k,v)
which is really only 1 additional line of code to provide the same API. It's safer because you never know what someone did to mess with Traits
to provide various descriptors (e.g. property) etc. setattr
will do all of that stuff correctly where blindly writing to __dict__
could be potentially harmful.
Post a Comment for "Adding Fields To A Class Via Setattr Vs. Storing A Dictionary In Python"