带有存根的子类的 Python 2.7 类型提示
Posted
技术标签:
【中文标题】带有存根的子类的 Python 2.7 类型提示【英文标题】:Python 2.7 type hinting for subclasses with stubs 【发布时间】:2018-10-19 16:43:52 【问题描述】:您可以根据https://www.python.org/dev/peps/pep-0484/#stub-files在 Python 2.7 中对存根文件使用类型提示
但是我不能让它适用于子类中的方法签名。
在存根文件 a.pyi 中:
class A(object):
def foo(self, timestamp: float): ...
在 Python 2.7 文件 b.py 中
class B(A):
def foo(self, timestamp):
print(timestamp) # Inferred type of timestamp is not float!
PyCharm 2017.3.3 不会将时间戳推断为浮点数。我没有检查 mypy 的行为。
有两种解决方法会导致代码冗余(不是首选)
解决方法 1
在存根文件 b.pyi 中
class B(A):
def foo(self, timestamp: float): ...
解决方法 2
在 Python 2.7 文件 b.py 中
class B(A):
def foo(self, timestamp): # type: (float) -> None
print(timestamp)
【问题讨论】:
【参考方案1】:如果您不向函数添加类型注释,则表明您不希望符合 PEP-484 的类型检查器检查该函数。
这意味着您需要执行方法 2:显式添加类型提示,以便 Pycharm(和 mypy)知道您希望对该函数进行类型检查。
请注意,您的解决方法 1 并没有真正起作用:如果您添加 *.pyi 文件,您就是在告诉类型检查器完全忽略相应的 *.py 文件。这可能不是您希望在这里发生的事情。
更广泛地说,Pycharm(或 mypy)推断timestamp
始终是float
类型实际上是不正确的:子类型实际上加宽 参数类型是合法的。例如,B
的时间戳方法可能接受浮点数或 strs:
class B(A):
def timestamp(self, timestamp):
# type: (Union[float, str]) -> None
print(timestamp)
或者它可以扩大到接受任何类型:
class B(A):
def timestamp(self, timestamp):
# type: (object) -> None
print(timestamp)
这两个定义都是 A 的有效子类型:它们都匹配 A.timestamp 的签名而不违反 Liskov substitution principle。
因此,由于我们不能轻易地自动推断出子类型的签名应该是什么,因此 Pycharm(和 mypy)不要尝试。
【讨论】:
这是有道理的。我希望通过覆盖一种方法,我建议应用相同的类型。没有考虑扩大。 @Michael0x2a 您对使用 pyi 存根的解决方法 1 的注释似乎与 PyCharm 不正确。类型检查器确实在 py 文件中合并了子 和 本地类型提示。以上是关于带有存根的子类的 Python 2.7 类型提示的主要内容,如果未能解决你的问题,请参考以下文章
带有列表的 Python 字典,如何在节俭的存根代码中描述它?
Python 类型提示 - 为 dict 子类指定键、值类型