ore*_*uro 7 python-3.x mypy python-typing pyright
考虑一个也用协议注释的 Python 协议属性。我发现在这种情况下,即使我的自定义数据类型遵循嵌套协议,mypy 和 Pyright 都会报告错误。例如,下面的代码Outer遵循协议,因为HasHasA它遵循协议。hasa: HasAInnerHasA
from dataclasses import dataclass
from typing import Protocol
class HasA(Protocol):
a: int
class HasHasA(Protocol):
hasa: HasA
@dataclass
class Inner:
a: int
@dataclass
class Outer:
hasa: Inner
def func(b: HasHasA): ...
o = Outer(Inner(0))
func(o)
Run Code Online (Sandbox Code Playgroud)
但是,mypy 显示以下错误。
nested_protocol.py:22: error: Argument 1 to "func" has incompatible type "Outer"; expected "HasHasA" [arg-type]
nested_protocol.py:22: note: Following member(s) of "Outer" have conflicts:
nested_protocol.py:22: note: hasa: expected "HasA", got "Inner"
Run Code Online (Sandbox Code Playgroud)
我的代码有什么问题吗?
GitHub 上有一个问题与您的示例几乎完全相同。我认为文档中的激励案例mypy很好地解释了为什么这是非法的。将结构类比到您的示例中,让我们填写一个实现func并Inner稍微调整一下:
def func(b: HasHasA) -> None:
b.hasa.a += 100 - 100
@dataclass
class Inner:
a: bool
o = Outer(Inner(bool(0)))
func(o)
if o.hasa.a is False:
print("Oh no! This is still False!")
else:
print("This is true now!")
Run Code Online (Sandbox Code Playgroud)
这当然是一个人为的示例,但它表明,如果类型检查器没有警告您注意这一点,则内部协议可以扩展内部类型并执行值突变,并且您可以默默地执行类型不安全的操作。
正如文档所建议的mypy,解决方案是将外部协议的变量设置为只读:
class HasHasA(Protocol):
@property
def hasa(self) -> HasA:
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |