在 A.__init__
中调用 self.func(argument)
:
class A(object):
def __init__(self, argument, key=0):
self.func(argument)
def func(self, argument):
#some code here
我想更改 B
中 A.func
的签名。 B.func
在 B.__init__
中通过 A.__init__
被调用:
class B(A):
def __init__(self, argument1, argument2, key=0):
super(B, self).__init__(argument1, key) # calls A.__init__
def func(self, argument1, argument2):
#some code here
显然,这是行不通的,因为 B.func
的签名需要两个参数,而 A.__init__
用一个参数调用它。我该如何解决这个问题?还是我设计类(class)的方式有问题?
key
是 A.__init__
的默认参数。 argument2
不适用于 key
。 argument2
是 B
采用但 A
不采用的额外参数。 B 也接受 key
并为其设置默认值。
另一个约束是我不想更改 A.__init__
的签名。 key
通常是 0
。所以我想让用户能够编写 A(arg)
而不是 A(arg, key=0)
。
最佳答案
一般来说,在子类之间更改方法的签名打破了子类上的方法实现与父类上的方法相同的 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)
# ...
传递给 super(B, self).__init__()
的第二个参数然后在 extra
元组中被捕获,并应用于 self.func( )
除了 argument
。
在 Python 2 中,要使用 extra
成为可能,您需要切换到使用 **kwargs
,否则 key
是总是会捕获第二个位置参数。确保使用 key=key
从 B
传递 key
。
在 Python 3 中,您不受此限制;将 *args
放在 key=0
之前,并且只使用 key
作为调用中的关键字参数:
class A(object):
def __init__(self, argument, *extra, key=0):
self.func(argument, *extra)
我也会给 func()
一个 *extra
参数,这样它的接口(interface)在 A
和B
;它只是忽略为 A
传递的第一个参数以及为 B
传递的前两个参数之外的任何内容:
class A(object):
# ...
def func(self, argument, *extra):
# ...
class B(A):
# ...
def func(self, argument1, argument2, *extra):
# ...
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>
关于python - 更改在基类的 __init__ 中调用的函数的签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36314522/