【问题标题】:Mypy: a generic that helps a decorator annotate a multiple dispatchMypy:帮助装饰器注释多个调度的泛型
【发布时间】:2019-12-06 10:30:35
【问题描述】:

我想将我的函数放在某个注册表中,并根据提供的一些参数(多重调度的一个版本)选择所需的函数。

这是示例代码:

method_registry = {}


def accepts(cls):
    """ A decorator that registers functions on some registry"""
    def register(func):
        method_registry[cls] = func
        return func

    return register


def handle(obj):
    """ Pick a function that corresponds to the provided object class and run it """
    handler = method_registry[obj.__class__]
    handler(obj)

现在,我打算如何使用它:


class Dog:
    def bark(self):
        print('bark')

class Cat:
    def meow(self):
        print('meow')


@accepts(Dog)
def handle_dog(obj):
    obj.bark()


@accepts(Cat)
def handle_cat(obj):
    obj.meow()


# Here comes multiple dispatch
handle(Dog())
handle(Cat())

现在,一切正常,但是当我尝试为 mypy 注释我的函数时,我必须输入 CatDog 两次:

@accepts(Dog)
def handle_dog(obj: Dog) -> None:
    obj.bark()


@accepts(Cat)
def handle_cat(obj: Cat) -> None:
    obj.meow()

所以,我猜一定有一种方法可以创建一个泛型类型,它可以为我注释我的obj-s 而无需复制代码。

但我似乎无法完成这项工作。

我的尝试是这样的:

V = TypeVar('V')

def accepts(cls: Type[V]) -> Callable[[Callable], Callable[[V], None]]:

    def register(func: Callable) -> Callable[[V], None]:
        method_registry[cls] = func
        return func

    return register

但这无济于事:

@accepts(Dog)
def handle_dog(obj) -> None:
    reveal_type(obj)  # Revealed type is 'Any'
    obj.bark()

有没有办法让它工作?

【问题讨论】:

  • AFAIK mypy 无法为您添加注释,因为它是静态代码分析器,应该手动完成

标签: python mypy


【解决方案1】:

当前的代码要求您指定两次类型:一次用于MyPy,一次用于accept。从理论上讲,这些类型可能会有所不同。

如果您想让它们都使用相同的值,则需要更改其中之一。 更改 accepts 方法比为 MyPy 编写插件要容易得多。通过检查您的函数的__annotations__ 字段,它可以使用相同的注释

def accepts():
    def register( func ):
        cls = func.__annotations__["obj"]
        method_registry[cls] = func
        return func
    
    return register

...

@accepts()
def handle_dog( obj: Dog ):
    obj.bark()

@accepts()
def handle_cat( obj: Cat ):
    obj.meow()

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2019-11-13
    • 2022-09-21
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多