可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a base class with a lot of __init__
arguments:
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
All the inheriting classes should run __init__
method of the base class.
I can write a __init__()
method in each of the inheriting classes that would call the superclass __init__
, but that would be a serious code duplication:
def A(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def C(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
...
What's the most Pythonic way to automatically call the superclass __init__
?
回答1:
super(SubClass, self).__init__(...)
Consider using *args and **kw if it helps solving your variable nightmare.
回答2:
You have to write it explicitly, but on the other hand, if you have lots of args, you should probably use *args for positional args and **kwargs for keyword args.
class SubClass(BaseClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)
# SubClass initialization code
Another technique you could use is to minimize the code in init and then at the end of init function, call another custom function. Then in the subclass, you just need to override the custom function
class BaseClass(object):
def __init__(self, *args, **kwargs):
# initialization code
self._a = kwargs.get('a')
...
# custom code for subclass to override
self.load()
def load():
pass
class SubClass(BaseClass)
def load():
# SubClass initialization code
...
回答3:
If the derived classes don't implement anything beyond what the base class __init__()
already does, just omit the derived classes __init__()
methods - the base class __init__()
is then called automatically.
If, OTOH, your derived classes add some extra work in their __init__()
, and you don't want them to explicitly call their base class __init__()
, you can do this:
class BaseClass(object):
def __new__(cls, a, b, c, d, e, f, ...):
new = object.__new__(cls)
new._a=a+b
new._b=b if b else a
...
return new
class A(BaseClass):
''' no __init__() at all here '''
class B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
''' do stuff with init params specific to B objects '''
Since __new__()
is always called automatically, no further work is required in the derived classes.
回答4:
Unless you are doing something useful in the subclass __init__()
methods, you don't have to override it.
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
def A(BaseClass):
def some_other_method(self):
pass
def B(BaseClass):
pass
回答5:
Perhaps a clearer implementation for your case is using **kwargs combined with new added arguments in your derived class as in:
class Parent:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
class Child(Parent):
def __init__(self, d, **kwargs):
super(Child, self).__init__(**kwargs)
self.d = d
By this method you avoid the code duplication but preserve the implicit addition of arguments in your derived class.
回答6:
In 2.6 and lower version to inherit init from base class, there is no super function, You can inherit below way:
class NewClass():
def __init__():
BaseClass.__init__(self, *args)
回答7:
Adding a Pythonic implementation. Assuming you want all attributes passed in, you can use the code below. (Can also keep/remove specific kwargs keys if you want a subset).
def A(BaseClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
base = BaseClass(...)
new = A( **base.__dict__ )