简体   繁体   English

为什么这个类变量在不同的实例中是相同的?

[英]Why is this class variable the same across different instances?

Why does i remain the same even after a new instance of the class is created? 为什么即使在创建了一个新的类实例后我仍保持不变?

class Test(object):
    i = 0
    def add(self):
        Test.i += 1

Running this code 运行此代码

t = Test()
print t.i
t.add()
t2 = Test()
print t2.i
print t.i

Gives

0
1
1

Why didn't both ti and t2.i equal 0? 为什么ti和t2.i都不等于0? Shouldn't they have equaled 0 because the line t2 = Test() would have reset i to 0? 它们不应该等于0,因为行t2 = Test()会将i重置为0吗?

i is a class variable, not an instance variable. i是一个类变量,而不是一个实例变量。 It is bound to the class itself (which is why you can write Test.i , even if no instances of Test exist). 它与类本身绑定(这就是为什么你可以编写Test.i ,即使没有Test实例存在)。

You have to make i an instance variable: 你必须使i成为一个实例变量:

class Test(object):
    def __init__(self):
        self.i = 0

    def add(self):
        self.i += 1

You are modifying a property of the entire class, instead of a property of the instance. 您正在修改整个类的属性,而不是实例的属性。 Try this: 尝试这个:

class Test(object):
    i = 0
    def add(self):
        self.i += 1

Python automatically passes the instance as the argument self to the method. Python自动将实例作为参数self传递给方法。 Within the method, you can therefore refer to a property of the instance as self.i . 因此,在该方法中,您可以将实例的属性称为self.i

class Test(object):
    i = 0
    def add(self):
        Test.i += 1

print "Test.i  == ",Test.i
print "'i' in dir(Test) == ",'i' in dir(Test)
print "'i' in Test.__dict__  == ",'i' in Test.__dict__

t1 = Test()
print '\n# t1 = Test() executed'
print "t1.i  == ",t1.i
print "'i' in dir(t1) == ",'i' in dir(t1)
print "'i' in t1.__dict__  == ",'i' in t1.__dict__

result 结果

Test.i  ==  0
'i' in dir(Test) ==  True
'i' in Test.__dict__  ==  True

# t1 = Test() executed
t1.i  ==  0
'i' in dir(t1) ==  True
'i' in t1.__dict__  ==  False

.

The attribute of name __dict__ of an object is the dictionary that represents the namespace of this object, that is to say it contains the attributes of the object. 对象的名称__dict__的属性是表示此对象的名称空间的字典,也就是说它包含对象的属性。

Also, we have: 此外,我们有:

dir([object]) DIR([对象])

If the object has a method named __dir__() , this method will be called and must return the list of attributes. 如果对象具有名为__dir__()方法,则将调用此方法,并且必须返回属性列表。

So, how is it possible that dir(t1) contains the attribute i and t1.__dict__ doesn't ? 那么, dir(t1)包含属性it1.__dict__不可能? While all two dir(Test) and Test.__dict__ contain the attribute i ? 虽然所有两个dir(Test)Test.__dict__包含属性i

.

That's for the same reason that answers to your question: 这与您的问题的答案相同:

The behavior of returning the attribute of an object is awkward. 返回对象属性的行为很尴尬。
And `dir(object) reflects this awkwardness: 并且`dir(object)反映了这种尴尬:

The default dir() mechanism behaves differently with different types of objects, as it attempts to produce the most relevant, rather than complete, information: 默认的dir()机制对不同类型的对象表现不同,因为它尝试生成最相关的信息,而不是完整的信息:

•If the object is a module object, the list contains the names of the module's attributes. •如果对象是模块对象,则列表包含模块属性的名称。
•If the object is a type or class object, the list contains the names of its attributes, and recursively of the attributes of its bases. •如果对象是类型或类对象,则列表包含其属性的名称,并递归地包含其基础的属性。
•Otherwise, the list contains the object's attributes' names , the names of its class's attributes , and recursively of the attributes of its class's base classes. •否则,列表包含对象的属性名称其类的属性的名称 ,以及其类的基类的属性的递归。

.

Then, the answer to your question is in two parts: 那么,你的问题的答案分为两部分:

1) dir(t1) gives what is considered as the attributes of the object but the REAL NAMESPACE of the object, exposed as t1.__dict__ doesn't contain the attribute i , which is, as it has already been answered, in fact, a class' atribute. 1) dir(t1)给出被认为是对象的属性,但是对象的真实NAMESPACE,暴露为t1.__dict__不包含属性i ,因为它已经被回答,实际上,一个类'属性。

Hence the pseudo-attributes i of two instances t1 and t2 appear equals because the expressions t1.i and t2.i are in fact evaluated as Test.i , 因此,两个实例t1t2的伪属性i看起来是等于的,因为表达式t1.it2.i实际上被评估为Test.i
in the same way that dir(t1) and dir(t2) include the class's attribute Test.i . dir(t1)dir(t2)包含类的属性Test.i

2) how the expression t1.i is evaluated as Test.i ?? 2)表达式t1.i如何被评估为Test.i ??
Because of that (which constitutes the additional info of my answer): 因此(构成我答案的附加信息):

A class instance has a namespace implemented as a dictionary which is the first place in which attribute references are searched. 类实例具有作为字典实现的名称空间,该字典是搜索属性引用的第一个位置。 When an attribute is not found there, and the instance's class has an attribute by that name, the search continues with the class attributes. 当在那里找不到属性,并且实例的类具有该名称的属性时,搜索继续使用类属性。

http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy

It means that when an attribute isn't found in the namespace of an object, it is searched in the namespace of the class whose the object is an instance. 这意味着当在对象的命名空间中找不到属性时,将在该对象是实例的类的命名空间中搜索它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM