Python 如何使用 __wrapped__ 键入提示 Callable
Python how to type hint a Callable with __wrapped__
传递函数时,我通常使用 typing.Callable
来提示它们。
collections.abc.Callable
的文档声明它有四种 dunder 方法:
class collections.abc.Callable
ABCs for classes that provide respectively the methods contains(), hash(), len(), and call().
有一次,我想检查函数上是否有 __wrapped__
属性。通过 hasattr(func, "__wrapped__")
.
检查,这在运行时工作正常
当使用 mypy
进行静态类型检查时,它报告:error: "Callable[..., Any]" has no attribute "__wrapped__" [attr-defined]
。这对我来说很有意义,因为 Callable
不应该有 __wrapped__
属性。
如何正确键入具有 __wrapped__
属性的 Callable
提示?我可以做一些其他类型的提示或解决方法吗?
代码示例
我正在使用 mypy==0.782
和 Python==3.8.2
:
from functools import wraps
from typing import Callable
def print_int_arg(arg: int) -> None:
"""Print the integer argument."""
print(arg)
@wraps(print_int_arg)
def wrap_print_int_arg(arg: int) -> None:
print_int_arg(arg)
# do other stuff
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
# error: "Callable[..., Any]" has no attribute "__wrapped__" [attr-defined]
print(f"func named {func.__name__} wraps {func.__wrapped__.__name__}.")
print_is_wrapped(wrap_print_int_arg)
显然,简单的答案是添加 # type: ignore
评论。然而,这实际上并没有解决问题,IMO。
我决定为具有 __wrapped__
属性的可调用对象创建一个类型存根。基于 ,这是我目前的解决方案:
from typing import Callable, cast
class WrapsCallable:
"""Stub for a Callable with a __wrapped__ attribute."""
__wrapped__: Callable
__name__: str
def __call__(self, *args, **kwargs):
...
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
func = cast(WrapsCallable, func)
print(f"func named {func.__name__} wraps {func.__wrapped__.__name__}.")
并且 mypy
现在报告 Success: no issues found in 1 source file
。
我觉得好像这是很多样板代码,希望有一个更精简的答案。
Mypy 抱怨在 print 语句中使用 __wrapped__
。
下面的技巧让 mypy 开心
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
wrapped_name = getattr(func, "__wrapped__").__name__
print(f"func named {func.__name__} wraps {wrapped_name}.")
传递函数时,我通常使用 typing.Callable
来提示它们。
collections.abc.Callable
的文档声明它有四种 dunder 方法:
class collections.abc.Callable
ABCs for classes that provide respectively the methods contains(), hash(), len(), and call().
有一次,我想检查函数上是否有 __wrapped__
属性。通过 hasattr(func, "__wrapped__")
.
当使用 mypy
进行静态类型检查时,它报告:error: "Callable[..., Any]" has no attribute "__wrapped__" [attr-defined]
。这对我来说很有意义,因为 Callable
不应该有 __wrapped__
属性。
如何正确键入具有 __wrapped__
属性的 Callable
提示?我可以做一些其他类型的提示或解决方法吗?
代码示例
我正在使用 mypy==0.782
和 Python==3.8.2
:
from functools import wraps
from typing import Callable
def print_int_arg(arg: int) -> None:
"""Print the integer argument."""
print(arg)
@wraps(print_int_arg)
def wrap_print_int_arg(arg: int) -> None:
print_int_arg(arg)
# do other stuff
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
# error: "Callable[..., Any]" has no attribute "__wrapped__" [attr-defined]
print(f"func named {func.__name__} wraps {func.__wrapped__.__name__}.")
print_is_wrapped(wrap_print_int_arg)
显然,简单的答案是添加 # type: ignore
评论。然而,这实际上并没有解决问题,IMO。
我决定为具有 __wrapped__
属性的可调用对象创建一个类型存根。基于
from typing import Callable, cast
class WrapsCallable:
"""Stub for a Callable with a __wrapped__ attribute."""
__wrapped__: Callable
__name__: str
def __call__(self, *args, **kwargs):
...
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
func = cast(WrapsCallable, func)
print(f"func named {func.__name__} wraps {func.__wrapped__.__name__}.")
并且 mypy
现在报告 Success: no issues found in 1 source file
。
我觉得好像这是很多样板代码,希望有一个更精简的答案。
Mypy 抱怨在 print 语句中使用 __wrapped__
。
下面的技巧让 mypy 开心
def print_is_wrapped(func: Callable) -> None:
"""Print if a function is wrapped."""
if hasattr(func, "__wrapped__"):
wrapped_name = getattr(func, "__wrapped__").__name__
print(f"func named {func.__name__} wraps {wrapped_name}.")