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

Yed*_*fir 8 python generics python-3.x functools

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

class A:
  @functools.singledispatchmethod
  def handle(arg):
     pass
Run Code Online (Sandbox Code Playgroud)

我希望其他类继承A并重载通用方法,handle如下所示:

class B(A):
   @handle.register
   def handle_int(arg: int):
       return arg + 2
Run Code Online (Sandbox Code Playgroud)

但是,我收到错误:

未解析的引用“句柄”

如何在基类中创建这个通用方法?(我不想在每个子类中创建此函数来使用singledispatchmethod。)

sop*_*ros 3

不理想的方法

由于您引用的是类中定义的方法,因此A您必须使用以下命令来指示它@A.handle.register

class B(A):
   @A.handle.register
   def handle_int(arg: int):
       return arg + 2
Run Code Online (Sandbox Code Playgroud)
问题

但是,当存在另一个类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+')
Run Code Online (Sandbox Code Playgroud)

结果:

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+)
Run Code Online (Sandbox Code Playgroud)