将整数更改为具有正确类型提示的字符串的装饰器

问题描述 投票:0回答:1

我想编写一个装饰器来更改某些参数的类型。

例如,任何

int
的参数都应该变成
str

from typing import Callable

def decorator(func: Callable) -> Callable:
    def wrapper(*args, **kwargs):
        modified_args = [str(arg) if isinstance(arg, int) else arg for arg in args]
        return func(*modified_args, **kwargs)
    return wrapper


@decorator
def my_function(a: int | str, b: int) -> str:
    return a + b

result = my_function('foo', 4)
print(result) 

这会输出

'foo4'
,如预期的那样

但是,

mypy
不高兴:

t.py:12: error: Incompatible return value type (got "Union[int, Any]", expected "str")  [return-value]
t.py:12: error: Unsupported operand types for + ("str" and "int")  [operator]
t.py:12: note: Left operand is of type "Union[int, str]"
Found 2 errors in 1 file (checked 1 source file)

有没有办法输入

decorator
以便在
my_function
的体内,mypy 会知道任何类型为
int
的参数已转换为
str

python mypy python-typing
1个回答
1
投票

def
声明必须使用实际传入和传出函数本身的参数的类型提示。装饰器或类似的包装器处理参数或返回值与最里面的函数无关。
然后,类型检查器考虑装饰器/包装器来派生实际的调用类型。

例如,用

@contextmanager
装饰的函数必须返回
:Iterator[T]
并且由 装饰器将其转换为
:ContextManager[T]


对于特定情况,这意味着

my_function
必须用它实际处理的类型进行注释 - 即
(str, str) -> str
。这样做的另一个好处是可以清楚地了解
a
b
在函数作用域中的含义:

@decorator  # < this must provide `:str, :str` but can receive whatever it wants
def my_function(a: str, b: str) -> str:
    # ^ the parameter types reflect what actually arrives in the function
    # v in this expression `a: str` and `b: str` in the signature
    return a + b

装饰

my_function
接受
a: int | str, b: int
decorator
关心的事,而不是
my_function

© www.soinside.com 2019 - 2024. All rights reserved.