类变量和实例变量之间的差异 [英] Difference between Class variables and Instance variables

查看:151
本文介绍了类变量和实例变量之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在Stack Exchange上阅读过许多答案,例如 Python - 为什么要使用自身在类中?
阅读完这些后,我理解实例变量对类的每个实例是唯一的,而类变量在所有实例之间共享。
在玩我发现这个代码 -

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

x = A()
y = A()
x.add $ b printY's x:,yx

会给出输出 1] 。但是,此代码 -

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

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

printY's x: ,yx

给出输出 10 在我看来应该 11
如果这是一个非常noobish的问题,请原谅我,但我在编程方面不是很有经验。

解决方案

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



这意味着在第二示例中:

  self.x + = 1 

(在这种情况下,请参见脚注)等效于:

  self.x = self.x + 1 


b $ b

Python所做的是:


  1. 查找 self.x 。在这一点上, self 没有实例属性 x ,因此类属性找到Ax ,值 10

  2. 对RHS进行求值, c $ c> 11 。

  3. 此结果分配给 x c $ c> self 。

xx ,您会得到在 add()中创建的新实例属性。查找 y.x 时,仍然会获得类属性。要更改类属性,您必须使用 Ax + = 1 显式 - 查找只会在读取属性的值时发生。






您的第一示例是一个经典的问题,您不应将类属性用作实例的默认值属性。当您调用:

  self.x.append(1)

没有对 self.x 的赋值。 (更改可变对象的内容,如 list 与赋值不同。)因此,没有新的实例属性添加到 x 会影响它,并查找 xx yx

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



(我从此SO回答解除了上述内容,请参阅有更多的细节。)


I have already read many answers here on Stack Exchange like Python - why use "self" in a class? After reading these I understand that instance variables are unique to each instance of the class while the class variable is shared across all instances. While playing around I found that this code -

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

x = A()
y = A()
x.add()
print "Y's x:",y.x

does give the output [1]. However, this code -

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

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

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

gives the output as 10 when in my opinion it should be 11. Please excuse me if this is a very noobish questions but I am not very experienced in programming.

解决方案

Class variables are shadowed by instance attribute. This means that when looking up an attribute, Python first looks in the instance, then in the class. Furthermore, setting a variable on an object (e.g. self) always creates an instance variable - it never changes the class variable.

This means that when, in your second example you do:

self.x += 1

which is (in this case, see footnote) equivalent to:

self.x = self.x + 1

what Python does is:

  1. Look up self.x. At that point, self doesn't have the instance attribute x, so the class attribute A.x is found, with the value 10.
  2. The RHS is evaluated, giving the result 11.
  3. This result is assigned to a new instance attribute x of self.

So below that, when you look up x.x, you get this new instance attribute that was created in add(). When looking up y.x, you still get the class attribute. To change the class attribute, you'd have to use A.x += 1 explicitly – the lookup only happens when reading the value of an attribute.


Your first example is a classical gotcha and the reason you shouldn't use class attributes as "default" values for instance attributes. When you call:

self.x.append(1)

there is no assignment to self.x taking place. (Changing the contents of a mutable object, like a list, is not the same as assignment.) Thus, no new instance attribute is added to x that would shadow it, and looking up x.x and y.x later on gives you the same list from the class attribute.


Note: In Python, x += y is not always equivalent to x = x + y. Python allows you to override the in-place operators separately from the normal ones for a type. This mostly makes sense for mutable objects, where the in-place version will directly change the contents without a reassignment of the LHS of the expression. However, immutable objects (such as numbers in your second example) do not override in-place operators. In that case, the statement does get evaluated as a regular addition and a reassignment, explaining the behaviour you see.

(I lifted the above from this SO answer, see there for more details.)

这篇关于类变量和实例变量之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆