问题描述
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
module 尝试以下操作。不过,这感觉有点像 hack,而且我不确定如何使其适用于类方法——以下解决方案仅适用于实例方法。
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
module,您或许能够更接近您想要的结果。我对它了解不多,但我认为它有一些 multipledispatch
没有的额外功能。