【发布时间】:2020-09-29 22:40:50
【问题描述】:
考虑以下将任何二元运算符扩展到多个参数的装饰器:
from typing import Callable, TypeVar
from functools import reduce, wraps
T = TypeVar('T')
def extend(binop: Callable[[T, T], T]):
""" Extend a binary operator to multiple arguments """
@wraps(binop)
def extended(*args: T) -> T:
if not args:
raise TypeError("At least one argument must be given")
return reduce(binop, args)
return extended
然后可以按如下方式使用:
@extend
def fadd(x: float, y: float) -> float:
""" Add float numbers """
return x + y
@extend
def imul(x: int, y: int) -> int:
""" Multiply integers """
return x*y
以便创建 imul 和 fadd 函数,它们分别将其输入参数相乘和相加。
函数imul 和fadd 将具有正确的文档字符串(因为@wraps 装饰器),但它们的签名和类型注释不正确。例如:
>>> help(fadd)
给予
fadd(x: float, y: float) -> float
Add float numbers
还有
>>> fadd.__annotations__
{'x': <class 'float'>, 'y': <class 'float'>, 'return': <class 'float'>}
这是不正确的。
实现装饰器以产生正确的函数签名的正确方法是什么?
我不知何故认为,如果我删除 @wraps 行,类型提示和签名将是正确的。但即便如此,也并非如此。没有@wraps
>>> help(fadd)
给予
extended(*args: ~T) -> ~T
(即泛型类型 T 不会被 float 替换)。
【问题讨论】:
标签: python-3.x python-decorators type-hinting