Swe*_*abh 4 python oop inheritance
我上课A。在中__init__,A我称为方法self.func(argument)。
class A(object):
def __init__(self, argument, key=0):
self.func(argument)
Run Code Online (Sandbox Code Playgroud)
类B是的子类A。在中B,我想更改的签名func。当我调用Afrom 的构造函数时会调用它B。
class B(A):
def __init__(self, argument1, argument2, key=0):
super(B, self).__init__(argument1, key) # can't send argument 2 to __init__ of A
def func(self, argument1, argument2):
#some code here
Run Code Online (Sandbox Code Playgroud)
显然,这是行不通的,因为Expect的签名func需要2个参数。我该如何解决?还是我设计课程的方式有问题?
key是A的默认参数__init__ 。argument2不适用于key。argument2是B接受而A则没有的额外论点。B也接受key并且具有默认值。
另一个限制是我不想更改A.的签名,key通常为0。因此,我希望允许用户能够编写A(arg)而不是A(arg, key=0)。
一般来说,在子类之间更改方法的签名会破坏对子类上的方法实现与父类上的API相同的API的期望。
但是,您可以重新设计您的工具A.__init__以允许任意附加的参数,并将其传递给self.func():
class A(object):
def __init__(self, argument, *extra, **kwargs):
key = kwargs.get('key', 0)
self.func(argument, *extra)
# ...
class B(A):
def __init__(self, argument1, argument2, key=0):
super(B, self).__init__(argument1, argument2, key=key)
# ...
Run Code Online (Sandbox Code Playgroud)
传递给第二个参数super(B, self).__init__(),然后在所捕获的extra元组,并应用到self.func()除了argument。
在Python 2中,要使其能够使用extra,就需要切换到using **kwargs,否则key总是会捕获第二个位置参数。确保传递key从B有key=key。
在Python 3中,您不受此限制的约束;放在调用*args之前key=0并且仅用key作关键字参数:
class A(object):
def __init__(self, argument, *extra, key=0):
self.func(argument, *extra)
Run Code Online (Sandbox Code Playgroud)
我也要提供func()一个*extra参数,以便它的接口在A和之间基本上保持不变B。它只会忽略传递给for的第一个参数以及传递给for A的前两个参数之外的所有内容B:
class A(object):
# ...
def func(self, argument, *extra):
# ...
class B(A):
# ...
def func(self, argument1, argument2, *extra):
# ...
Run Code Online (Sandbox Code Playgroud)
Python 2演示:
>>> class A(object):
... def __init__(self, argument, *extra, **kwargs):
... key = kwargs.get('key', 0)
... self.func(argument, *extra)
... def func(self, argument, *extra):
... print('func({!r}, *{!r}) called'.format(argument, extra))
...
>>> class B(A):
... def __init__(self, argument1, argument2, key=0):
... super(B, self).__init__(argument1, argument2, key=key)
... def func(self, argument1, argument2, *extra):
... print('func({!r}, {!r}, *{!r}) called'.format(argument1, argument2, extra))
...
>>> A('foo')
func('foo', *()) called
<__main__.A object at 0x105f602d0>
>>> B('foo', 'bar')
func('foo', 'bar', *()) called
<__main__.B object at 0x105f4fa50>
Run Code Online (Sandbox Code Playgroud)