mou*_*ail 5 python type-hinting python-3.9
假设我有一个实现方法链的类:
from __future__ import annotations
class M:
def set_width(self, width: int)->M:
self.width = width
return self
def set_height(self, height: int)->M:
self.height = height
return self
Run Code Online (Sandbox Code Playgroud)
我可以这样使用它:
box = M().set_width(5).set_height(10)
Run Code Online (Sandbox Code Playgroud)
这有效,但如果我有一个子类 M3D:
class M3D(M):
def set_depth(self, depth: int) -> M3D:
self.depth = depth
return self
Run Code Online (Sandbox Code Playgroud)
现在我不能这样做:
cube = M3D().set_width(2).set_height(3).set_depth(5)
Run Code Online (Sandbox Code Playgroud)
我在 mypy 中收到以下错误:
_test_typeanotations.py:21: error: "M" has no attribute "set_depth"; maybe "set_width"
Run Code Online (Sandbox Code Playgroud)
因为set_width()返回一个M没有方法set_depth。我已经看到建议覆盖set_width()并set_height()为每个子类指定正确的类型,但是为每个方法编写大量代码。必须有更简单的方法。
这也与特殊方法相关,例如__enter__传统上的返回self,因此最好有一种方法来指定它,而无需在子类中提及它。
Boš*_*jak 14
从 Python 3.11 开始,您可以执行以下操作:
from typing import Self
class M:
def set_width(self, width: int) -> Self:
self.width = width
return self
Run Code Online (Sandbox Code Playgroud)
经过大量的研究和实验,我找到了一种在 mypy 中有效的方法,尽管 Pycham 有时仍然会猜测类型错误。
诀窍是创建self一个 var 类型:
from __future__ import annotations
import asyncio
from typing import TypeVar
T = TypeVar('T')
class M:
def set_width(self: T, width: int)->T:
self.width = width
return self
def set_height(self: T, height: int)->T:
self.height = height
return self
def copy(self)->M:
return M().set_width(self.width).set_height(self.height)
class M3D(M):
def set_depth(self: T, depth: int) -> T:
self.depth = depth
return self
box = M().set_width(5).set_height(10) # box has correct type
cube = M3D().set_width(2).set_height(3).set_depth(5) # cube has correct type
attemptToTreatBoxAsCube = M3D().copy().set_depth(4) # Mypy gets angry as expected
Run Code Online (Sandbox Code Playgroud)
最后一行在 mypy 中工作得很好,但 pycharmset_depth有时仍然会自动.copy()完成,M即使在M3D.
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |