python - 这个装饰器类型注释是否正确?
问题描述
from functools import wraps
from typing import Any, Callable
def timer(func: Callable[..., Any]) -> Callable[..., Any]:
"""Calculates the runtime of a function, and outputs it to logging.DEBUG."""
@wraps(func)
def wrapper(*args, **kwargs):
start = perf_counter()
value = func(*args, **kwargs)
end = perf_counter()
_logger = logging.getLogger(__name__ + "." + func.__name__)
_logger.debug(" runtime: {:.4f} seconds".format(end - start))
return value
return wrapper
解决方案
这种方法的问题在于,现在 MyPy 丢失了返回类型,或者更确切地说,它退化为Any
,因此请考虑:
import logging
from typing import Callable, Any
from time import perf_counter
from functools import wraps
def timer(func: Callable[..., Any]) -> Callable[..., Any]:
"""Calculates the runtime of a function, and outputs it to logging.DEBUG."""
@wraps(func)
def wrapper(*args, **kwargs):
start = perf_counter()
value = func(*args, **kwargs)
end = perf_counter()
_logger = logging.getLogger(__name__ + '.' + func.__name__)
_logger.debug(' runtime: {:.4f} seconds'.format(end - start))
return value
return wrapper
@timer
def func(x:int) -> int:
return x
def string_func(s: str):
return s[:]
x = 42 * func(42)
reveal_type(x)
string_func(x)
使用:
(py37) Juans-MacBook-Pro:tempdata juan$ mypy --version
mypy 0.641
如果我尝试对此进行类型检查,它会通过!
(py37) Juans-MacBook-Pro:tempdata juan$ mypy typing_decorators.py
typing_decorators.py:29: error: Revealed type is 'Any'
如果您想准确保留参数,我找到了一种解决方案,即使用 a TypeVar
and 到cast
包装器,这样 MyPy 可以准确地知道类型(假设原始函数已注释):
import logging
from typing import Callable, Any, TypeVar, cast
from time import perf_counter
from functools import wraps
F = TypeVar('F', bound=Callable[..., Any])
def timer(func: F) -> F:
"""Calculates the runtime of a function, and outputs it to logging.DEBUG."""
@wraps(func)
def wrapper(*args, **kwargs):
start = perf_counter()
value = func(*args, **kwargs)
end = perf_counter()
_logger = logging.getLogger(__name__ + '.' + func.__name__)
_logger.debug(' runtime: {:.4f} seconds'.format(end - start))
return value
return cast(F, wrapper)
@timer
def func(x:int) -> int:
return x
def string_func(s: str):
return s[:]
x = 42 * func(42)
reveal_type(x)
string_func(x)
在这种情况下:
(py37) Juans-MacBook-Pro:tempdata juan$ mypy typing_decorators.py
typing_decorators.py:32: error: Revealed type is 'builtins.int'
typing_decorators.py:34: error: Argument 1 to "string_func" has incompatible type "int"; expected "str"
推荐阅读
- angular - Angular Ionic Side Drawer 不渲染
- java - Javafx 中屏幕之间的参数
- python - 如何从多订单模型中获取项目模型的总和?
- alphametic-question - 调查文本中的随机forloop?
- r - 如何根据两个向量的组合命名 R 中的列?
- c# - 读取文件签名并区分 zip 文件和 docx 文件
- python - 使用 Discord.py-Rewrite 保存所有服务器成员的数组
- android - 浮动操作按钮上的 stateListAnimator 不起作用
- rust - 只是从“如果让”得到一个布尔结果?
- python - 返回一直给我没有?