Is there a shortcut for `self.somevariable = somev

2019-04-29 04:55发布

问题:

Constructors in Python often look like this:

class SomeClass:
    def __init__(self, a, b = None, c = defC):
        self.a = a
        self.b = b or []
        self.c = c

Is there a shortcut for this, e.g. to simply define __init__(self,**kwargs) and use the keys as properties of self?

回答1:

One problem with

self.__dict__.update(locals())

is that it includes self, so you get self.self. It would be better to filter self out of locals()

eg.

vars(self).update((k,v) for k,v in vars().items() if k != 'self')

You can defend against accidentally overwriting methods with this variation

vars(self).update((k,v) for k,v in vars().items()
                   if k != 'self' and k not in vars(self))

If you don't want it to fail silently, you could also check beforehand like this

if any(k in vars(self) for k in vars()):
    raise blahblah
vars(self).update((k,v) for k,v in vars().items() if k != 'self')


回答2:

One idiom I've seen is self.__dict__.update(locals()). If you run it right at the beginning of the method, this will update the object's dictionary with the arguments (since those are the only locals at the beginning of the method). If you pass in **kwargs you can do self.__dict__.update(**kwargs).

Of course, this is a fragile approach. It can lead to puzzling bugs if you accidentally pass in an argument that masks an existing attribute. For instance, if your class has a .doSomething() method and you accidentally pass doSomething=1 to the constructor, it will override the method and cause an error later if you try to call that method. For this reason it's better not to do this except in certain trivial cases (e.g., some sort of proxy object whose only purpose is to serve as a "bag" holding a few attributes).



回答3:

Yes:

class SomeClass:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)