Python函数返回内部类的返回类型注解及装饰器优化方案
为返回内部类的Python函数标注返回类型
针对你用可调用类实现装饰器的场景,有两种无需暴露额外基类的类型标注方案:
方案一:使用私有Protocol(精确描述接口)
通过定义模块私有的Protocol(Python 3.8+,3.7及以下需安装typing_extensions),可以精确描述内部Wrapper类的接口,同时避免污染公共命名空间:
from functools import wraps from typing import Any, Callable, Protocol # 私有协议,仅用于类型标注,不对外暴露 class _WrapperProtocol(Protocol): def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]: ... def decorator(*args: Any, **kwargs: Any) -> _WrapperProtocol: class Wrapper: def __init__(self) -> None: self.args = args self.kwargs = kwargs def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]: @wraps(func) def wrapper(*args: Any, **kwargs: Any) -> Any: return func(*args, **kwargs) return wrapper return Wrapper()
_WrapperProtocol以下划线开头,属于模块私有成员,不会被from module import *导入,完美解决基类暴露的问题。
方案二:直接标注为嵌套Callable类型
如果只需要描述Wrapper的可调用行为(不需要关注其内部属性如args/kwargs),可以直接用嵌套的Callable类型标注,无需额外定义类:
from functools import wraps from typing import Any, Callable def decorator(*args: Any, **kwargs: Any) -> Callable[[Callable[..., Any]], Callable[..., Any]]: class Wrapper: def __init__(self) -> None: self.args = args self.kwargs = kwargs def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]: @wraps(func) def wrapper(*args: Any, **kwargs: Any) -> Any: return func(*args, **kwargs) return wrapper return Wrapper()
如果觉得类型签名过长,还可以用TypeAlias简化(Python 3.10+):
from typing import TypeAlias, Callable, Any # 私有类型别名,简化标注 _DecoratorWrapper: TypeAlias = Callable[[Callable[..., Any]], Callable[..., Any]] def decorator(*args: Any, **kwargs: Any) -> _DecoratorWrapper: # 内部代码不变
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

