我正在努力学习Python变量注释。根据PEP-0526,我们现在有了类似于:
class BasicStarship:
captain: str = 'Picard' # instance variable with default
damage: int # instance variable without default
stats: ClassVar[Dict[str, int]] = {} # class variable
这是一个艰难的周末,我的Python有点生疏,但我认为未分配给self的声明变量是类变量。以下是一些有趣的例子:
class BasicStarship:
captain: str = 'Picard' # instance variable with default
def __init__(self,name):
self.captain = name
wtf = BasicStarship('Jim')
BasicStarship.captain = 'nope'
print(wtf.captain) #=> Jim
上面的代码正如我所期望的那样工作。不过下面有点让我困惑
class BasicStarship:
captain: str = 'Picard' # instance variable with default
wtf = BasicStarship()
BasicStarship.captain = 'nope'
print(wtf.captain) #=> 'nope'
在第二个例子中,我希望是“Picard”而不是“nope”。我觉得我缺少了一些关于类变量和实例变量的规则。在某种程度上,我认为执行BasicStarship.captain
会导致类错误,因为captain
是一个实例变量(在第一个示例中,不确定在第二个示例中)。您是否总是能够在类声明之后定义实例变量(在方法之外)?类和实例变量之间是否存在某种相互作用,从而使这一点更清楚
使用Python 3.6.3运行的代码
这是类变量和实例变量的正常相互作用。它与打字无关
您的错误是这里的措辞:
captain
不是此处的实例变量。这定义了一个类变量,当未设置相应的实例变量时,该类变量作为默认值。但是类变量和实例变量是两个独立的东西请注意,类型仅由静态类型检查器进行计算,而不是由Python解释器本身进行计算。因此,这两者之间不存在任何运行时语义差异:
在运行时,它们都是空字典对类变量的赋值。如果注释使其中一个定义了实例变量,而另一个定义了类变量,则会违反键入不能具有运行时效果的规则。
ClassVar
下的注释具有误导性,尽管文本给出了关于其含义的提示:注释用于指示变量将如何使用的意图。类型检查器假设上面的foo
将从实例(checked_quux.foo
)访问,并且可能会被实例变量覆盖,而bar
不应在实例上访问,而应仅在类(CheckedQuux.bar
)上访问,如果我们试图在实例(checked_quux.bar
)上访问它,则应引发类型检查错误我同意您对文档的一些困惑,因为您的示例中的
captain
似乎是类属性而不是实例属性考虑如下:
如您所料(根据您的问题),此打印:
然而,这很有趣:
结果:
因此,
wtf1
没有一个名为captain
的属性,因此使用名为captain
的类属性(解释了当您更改它时为什么会更改)wtf2
确实有一个名为captain
的属性,因此它会覆盖class属性BasicStarship
显示class属性这一切都是有意义的,并且与实际文档中给出的示例类似,唯一令人困惑的部分是描述为
instance variable with default
,因为它似乎更正确,为class variable with default
(在Python 3.7.5上,其他方面相同)
相关问题 更多 >
编程相关推荐