我想将我的函数放在某个注册表中,并根据提供的一些参数(多个调度的版本)选择所需的函数。
这是示例代码:
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注释函数时,我必须两次键入Cat
和Dog
:
@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()
有没有办法使这项工作成功?
答案 0 :(得分:0)
目前的代码要求您指定两次类型:一次用于 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()