我试图确保服务器已设置装饰器, 代码按预期运行,但 mypy 给了我一个 union-attr 错误。
这是一个例子:
from functools import wraps
class Server:
def __init__(self, ip) -> None:
self.ip = ip
_server: Server | None = None
def ensure_server(func):
"""Ensure a server connection has been set"""
@wraps(func)
def wrapper(*args, **kwargs):
global _server
if _server is None:
raise ValueError("server is None")
return func(*args, **kwargs)
return wrapper
@ensure_server
def hello_server():
print(_server.ip)
def add_server(foo: str):
print(_server.ip + foo)
Mypy 处理
hello_server
没有任何错误,但在 Item "None" of "Server | None" has no attribute "ip"
中给出 add_server
。
为什么 mypy 对带参数的函数给出错误,而对没有参数的函数则不给出错误?
这里有两个问题。第一个问题是你没有把
@ensure_server
放在 add_server
上,所以你实际上并没有得到你认为在那里的保证。
但这并不是触发 mypy 行为的原因。
hello_server
没有注释,所以 mypy 根本不检查它。 mypy 不知道装饰器做了什么,也没有办法告诉 mypy 装饰器确保了你想要的不变量。