如何将singledispatchmethod与继承类一起使用



在我的代码中,我有以下类:

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中实现您想要做的事情有点困难。singledispatchsingledispatchmethod本身都是语言中相对的新特征。更复杂的重载,比如你正在尝试的重载,目前并没有得到很好的支持(据我所知(。

话虽如此,您可以使用第三方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没有的额外功能。

相关内容

  • 没有找到相关文章

最新更新