我不确定Python对类型暗示实例变量的约定——我一直在__init__构造函数参数like seen here中使用它们:

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value`

但我也看到了PEP的惯例,即注释实例变量(下面的代码片段),然后在__init__个参数中进行类型暗示:

class BasicStarship:
    captain: str = 'Picard'               # instance variable with default
    damage: int                           # instance variable without default
    stats: ClassVar[Dict[str, int]] = {}  # class variable`

    def __init__(self, damage: int, captain: str = None):
        self.damage = damage
        if captain:
            self.captain = captain  # Else keep the default

最后,在PEP 526的文章后面,他们说为了方便和惯例,可以做以下事情:

class Box(Generic[T]):
    def __init__(self, content):
        self.content: T = content

(以上两段代码都来自here.)

那么,这些约定中有一个比我应该坚持的其他约定(更好的可读性等)更好/更被广泛接受吗?

推荐答案

我建议使用第一个版本,在大多数情况下,将类型分配给__init__个方法的参数.

该特定方法具有最少的冗余,同时仍然允许类型判断器验证您在代码的其他地方正确调用了该__init__方法.

我建议使用第二个或第三个版本,当__init__方法变得足够复杂,可以应用以下一个或多个选项时,可以显式地注释字段(在__init__之内或之外):

  1. 你的领域从什么开始就不再那么简单了
  2. 参数和字段之间不再存在一对一的映射
  3. 你有复杂的初始化逻辑,模糊了你的字段是如何分配的.

然而,我不清楚第二个版本还是第三个版本更受欢迎——我个人更喜欢第三个版本,因为它在概念上更清晰,似乎没有混合实例和类属性的概念,但我不能否认第二个版本看起来更清晰.

我在"键入"gitter频道上询问了这个问题,并从Guido那里得到了以下回复(你可能不知道,他制作了Python,目前正在研究mypy和键入相关的东西):

不管怎样,似乎都有强烈的意见.我确实更喜欢在类主体中添加属性注释,而不是在__init__和其他方法中添加属性注释.我还认为,有了PEP 526,这将是future 的趋势(还有基于类的NamedTuple声明和可能的https://github.com/ericvsmith/dataclasses).

(link to quote)

因此,第二个版本似乎比第三个版本更受欢迎,而且以这种方式定义类将在将来的某个时候更深入地融入Python语言本身!

Edit:PEP 557, data classesrecently accepted,似乎在轨道上(?)将包含在Python 3.7中.

Python-3.x相关问答推荐

海象表达可以放在方括号中而不是括号中吗?

Pandas 中每行的最大值范围

字符串块数组:如何根据一个数组中的元素对另一个数组中的元素进行分组

循环遍历数据框以提取特定值

具有多个值的极轴旋转和熔化/取消旋转(反转旋转)操作(Pandas 堆叠/取消堆叠交替/UDF覆盖)

将strid()映射到Pandas DataFrame中的字符串不会更改NaN条目,但仍然声称它们不同?

如何在输入正确的用户名和密码时添加按钮?

类变量的Python子类被视为类方法

在 Python 中实现 COM 接口

考虑到Pandas 系列中的不同索引,如何正确估计两列的百分比变化? Python相关

如何在数据['column']中的'string'等条件下应用pandas

在判断列表变量时如何判断特定列的值并分配加权整数值

是否将dict转换为一个数据帧,每个值都有重复的键?

请求:RecursionError:超出最大递归深度

如何判断一个字符串是否包含有效的 Python 代码

在 Python 3 中获取所有超类

BeautifulSoup 的 Python 3 兼容性

Python的max函数有多高效

Python 3 中的连接列表

如何判断列表中的所有项目是否都是字符串