【问题标题】:Python 2.7 type hinting for subclasses with stubs带有存根的子类的 Python 2.7 类型提示
【发布时间】: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)

【问题讨论】:

    标签: python-2.7 pycharm type-hinting


    【解决方案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 文件中合并了子 本地类型提示。
    猜你喜欢
    • 2017-11-30
    • 2017-10-09
    • 2017-10-14
    • 2017-11-01
    • 2021-12-01
    • 2020-11-23
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多