在我的代码中,我有以下类:
class A:
@functools.singledispatchmethod
def handle(arg):
pass
我希望其他类从A
继承并重载泛型方法handle
,如下所示:
class B(A):
@handle.register
def handle_int(arg: int):
return arg + 2
然而,我得到了一个错误:
未解析引用"句柄">
如何在基类中创建此泛型方法?(我不想在每个子类中创建这个函数来使用singledispatchmethod
。(
不是理想的方法
由于您引用的是类A
中定义的方法,因此必须使用@A.handle.register
:来指示它
class B(A):
@A.handle.register
def handle_int(arg: int):
return arg + 2
问题
但是,当存在另一个类C
时,这种方法会引起问题,该类也继承自A
,但支持handle(arg: str)
。然后C().handle(2)
将从类B
调用方法,因为它已注册到A
方法(即使它最终应该在类A
的基句柄方法中(。
更好的方法
上述解决方案的明显问题是一个注册类(A
(,因此我在所有派生类中添加了注册,但在派生类中没有适当类型的专用类方法的情况下,将处理留给基类。
import functools
class A:
@functools.singledispatchmethod
def handle(arg):
print(f'tA handle (arg: {arg})')
class B(A):
@functools.singledispatchmethod
@classmethod
def handle(cls, arg):
print(f'tB handle (arg: {arg})')
return super(B, cls).handle(arg)
@B.handle.register
def handle_int(arg: int):
print(f'tB int (arg: {arg})')
return arg + 2
class C(A):
@functools.singledispatchmethod
@classmethod
def handle(cls, arg):
print(f'tC handle (arg: {arg})')
return super(C, cls).handle(arg)
@C.handle.register
def handle_str(arg: str):
print(f'tC str (arg: {arg})')
return arg + ' 2'
print('nA')
A.handle(2)
A.handle('2+')
print('nB')
B.handle(2)
B.handle('2+')
print('nC')
C.handle(2)
C.handle('2+')
结果:
A
A handle (arg: 2)
A handle (arg: 2+)
B
B int (arg: 2)
B handle (arg: 2+)
A handle (arg: 2+)
C
C handle (arg: 2)
A handle (arg: 2)
C str (arg: 2+)
在Python中实现您想要做的事情有点困难。singledispatch
和singledispatchmethod
本身都是语言中相对的新特征。更复杂的重载,比如你正在尝试的重载,目前并没有得到很好的支持(据我所知(。
话虽如此,您可以使用第三方multipledispatch
模块尝试以下操作。不过,这感觉有点像黑客攻击,我不知道如何在类方法上使用它——下面的解决方案只适用于实例方法。
from multipledispatch import dispatch
@dispatch(object, object)
def handle(instance, arg):
return 'Base implementation'
class A:
def handle(self, arg):
return handle(self, arg)
class B(A):
pass
class C(A):
pass
@dispatch(B, int)
def handle(instance, arg):
return 'Specialised implementation for class B and ints'
@dispatch(C, str)
def handle(instance, arg):
return 'Specialised implementation for class C and strs'
a, b, c = A(), B(), C()
print(a.handle('hi')) # prints "Base implementation"
print(b.handle('hi')) # prints "Base implementation"
print(b.handle(3)) # prints "Specialised implementation for class B and ints"
print(c.handle(3)) # prints "Base implementation"
print(c.handle('hi')) # prints "Specialised implementation for class C and strs"
使用pip上的另一个第三方模块plum-dispatch
,您可能能够更接近您想要的结果。我对它了解不多,但我认为它有一些multipledispatch
没有的额外功能。