Is there a shortcut for `self.somevariable = somev

2019-04-29 04:18发布

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?

3条回答
爷的心禁止访问
2楼-- · 2019-04-29 04:55

Yes:

class SomeClass:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
查看更多
神经病院院长
3楼-- · 2019-04-29 05:09

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).

查看更多
家丑人穷心不美
4楼-- · 2019-04-29 05:15

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')
查看更多
登录 后发表回答