python - 类变量和实例变量的区别

标签 python class oop

我已经在 Stack Exchange 上阅读了很多答案,例如 Python - why use "self" in a class? 阅读这些答案后,我了解到实例变量对于类的每个实例都是唯一的,而类变量在所有实例之间共享。

在玩游戏时,我发现这段代码给出了输出[1]:

class A:
    x = []
    def add(self):
        self.x.append(1)

x = A()
y = A()
x.add()

print "Y's x: ", y.x

然而,这段代码给出了 10 作为输出,而在我看来它应该是 11:

class A:
    x = 10
    def add(self):
        self.x += 1

x = A()
y = A()
x.add()

print "Y's x: ", y.x

为什么 A 类变量在我运行 x.add() 时没有更新?我在编程方面不是很有经验,所以请原谅。

最佳答案

类变量被实例属性隐藏。这意味着在查找属性时,Python 首先在实例中查找,然后在类中查找。此外,在对象上设置变量(例如 self)总是会创建一个实例变量 - 它永远不会更改类变量。

这意味着当您在第二个示例中执行以下操作时:

self.x += 1

这(在本例中,请参见脚注)等同于:

self.x = self.x + 1

Python 所做的是:

  1. 查找self.x。此时,self 没有实例属性 x,因此找到了类属性 A.x,其值为 10
  2. 计算 RHS,给出结果 11
  3. 此结果分配给 self 的新实例属性 x

因此在下面,当您查找 x.x 时,您将获得在 add() 中创建的这个新实例属性。在查找 y.x 时,您仍然可以获得类属性。要更改类属性,您必须显式使用 A.x += 1 - 查找仅在读取属性值时发生。


您的第一个 示例是一个典型的陷阱,也是您不应将类属性用作实例属性的“默认”值的原因。当你打电话时:

self.x.append(1)

没有对 self.x 进行赋值。 (更改可变对象的内容,如列表,与赋值不同。)因此,没有新的实例属性添加到x 会隐藏它,稍后查找 x.xy.x 会为您提供来自类属性的相同列表。


注意:在 Python 中,x += y 并不总是等同于 x = x + y。 Python 允许您分别覆盖类型的就地运算符和普通运算符。这主要适用于可变 对象,其中就地版本将直接更改内容,无需 重新分配表达式的 LHS。但是,不可变 对象(例如第二个示例中的数字)不会覆盖就地运算符。在这种情况下,该语句确实会被评估为常规添加和重新分配,从而解释您看到的行为。

(我从 this SO answer 中提取了上面的内容,有关更多详细信息,请参阅此处。)

关于python - 类变量和实例变量的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19753897/

相关文章:

python - 如何定期检查程序中的当前日期?

python - python 'Resource' 对象中的 Freebase API 没有属性 'mqlread'

c++ - 在类中创建函数的问题

没有 .cpp 文件的 C++ 类?

c# - 使用事件处理程序作为 "reusable code"是不好的做法吗?

python - 堆叠一个方形 DataFrame 以仅保留上/下三角形

python - 使用 Flask 和 Gunicorn 设置 Google 凭据

c++ - 如何在 C++ OOP 中正确使用类中的函数

ios - 什么应该拥有 MVC 模式中的模型?

oop - 我应该如何在数据库和 OOP 中建模组关系?