使用 python 2 类型注释指定实例变量的类型

Posted

技术标签:

【中文标题】使用 python 2 类型注释指定实例变量的类型【英文标题】:Specify type of instance variables using python 2 type comments 【发布时间】:2020-01-13 01:05:20 【问题描述】:

我正在尝试使用 PEP 484 的 python 2 syntax 指定实例变量的类型。但是,在python 2中我还没有找到任何不初始化变量的添加类型的方法,相当于下面的python 3:

value: int

我的正常工作是在实例化变量时在__init__ 中声明变量的类型。但是,这不适用于实例变量的类型应该是协议的一部分的协议(__init__ 中的类型似乎不算在内)。这是 Python 3 中我使用默认实现的示例:

from typing_extensions import Protocol
class A(Protocol):
    value: int

    def get_value(self) -> int:
        return self.value

如果 value 未正确初始化,这将突出显示错误:

class B(A):
    pass
B()  # error: Cannot instantiate abstract class 'B' with abstract attribute 'value'

但是,将其转换为 python 2 类型 cmets 无法通过 mypy.无论有没有__init__ 声明,它都会给出相同的错误。

class A(Protocol):
    def __init__(self):
        # type: () -> None
        self.value = 0  # type: int
    def get_value(self):
        # type: () -> int
        return self.value  # error: "A" has no attribute "value"

是否有一些特殊的语法可以声明变量类型而不在 python 2 中初始化它们?

【问题讨论】:

我猜这就是为什么 Protocol 在 2.7 中位于 typing_extensions 而不是 typing @BoarGules 这是一个非常无益的评论,因为它暗示这是在 mypy 中做出的明确决定。它看起来更像是一个错误。 【参考方案1】:

Mypy 的协议使用类变量 来定义属性。否则 mypy 不会在类变量和实例变量之间做出特别好的区分。把这两件事放在一起,你可以写出如下代码:

from typing_extensions import Protocol

class A(Protocol):
    value = None  # type: int

    def get_value(self):
        # type: () -> int
        return self.value

# below here it's just to validate that the protocol works

class B(object):
    def __init__(self, value):
        # type: (int) -> None
        self.value = value

    def get_value(self):
        # type: () -> int
        return self.value


a = B(42)  # type: A

【讨论】:

这行得通,令我惊讶! A.value 是类变量而不是实例变量;然而,mypy 似乎也接受带有实例变量的对象作为实现A。将 B 更改为 def __init__(self): self.value = 42(实例变量)类型检查很好,这正是我想要的。 如果您更新答案以使用B 中的实例变量,我会接受。 完成!我认为在更新这个答案的过程中,我开始更好地理解这个问题。

以上是关于使用 python 2 类型注释指定实例变量的类型的主要内容,如果未能解决你的问题,请参考以下文章

Python基础之变量,常量,注释,数据类型

Python 2 类型注释 - 如何指定返回类型是特定类的类型或子类型?

Python基础

Python基础之注释变量Debug调试数据类型

变量和简单数据类型--注释

python 3.5代码中的变量需要类型注释