gpt4 book ai didi

python-3.x - 如何更正装饰函数签名和类型提示?

转载 作者:行者123 更新时间:2023-12-03 20:52:12 26 4
gpt4 key购买 nike

考虑以下将任何二元运算符扩展为多个参数的装饰器:

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

从而创建 imulfadd分别乘以和相加它们的输入参数的函数。

功能 imulfadd将有正确的文档字符串(因为 @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 替换)。

最佳答案

我使用 inspect 找到了一个有点棘手的解决方案

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)

sig = inspect.signature(extended)

sig = sig.replace(
parameters=[inspect.Parameter('args', inspect.Parameter.VAR_POSITIONAL,
annotation=sig.return_annotation)]
)

extended.__signature__ = sig

return extended

它并不像我预期的那么优雅,尤其是因为它在很大程度上取决于 binop 的事实。返回值必须与其参数具有相同的类型(否则注释将是错误的)。

然而,我很高兴知道更好的解决方案。

关于python-3.x - 如何更正装饰函数签名和类型提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62304871/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com