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

Python 为什么这个类变量在不同的实例中是相同的?,python,oop,class,Python,Oop,Class,为什么即使创建了类的新实例,我仍然保持不变 class Test(object): i = 0 def add(self): Test.i += 1 运行此代码 t = Test() print t.i t.add() t2 = Test() print t2.i print t.i 给予 为什么t.i和t2.i不都等于0?它们不应该等于0,因为行t2=Test()会将i重置为0吗?i是类变量,而不是实例变量。它绑定到类本身(这就是为什么您可以编写Test.i

为什么即使创建了类的新实例,我仍然保持不变

class Test(object):
    i = 0
    def add(self):
        Test.i += 1
运行此代码

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


为什么t.i和t2.i不都等于0?它们不应该等于0,因为行
t2=Test()
会将i重置为0吗?

i
是类变量,而不是实例变量。它绑定到类本身(这就是为什么您可以编写
Test.i
,即使不存在
Test
的实例)

您必须使
i
成为一个实例变量:

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

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

您正在修改整个类的属性,而不是实例的属性。试试这个:

class Test(object):
    i = 0
    def add(self):
        self.i += 1
Python会自动将实例作为参数
self
传递给方法。因此,在该方法中,您可以将实例的属性引用为
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__
结果

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

对象的name
\uuuu dict\uuuu
属性是表示该对象名称空间的字典,也就是说它包含该对象的属性

此外,我们还有:

目录([对象])

如果对象有一个名为
\uuuu dir\uuu()
的方法,则将调用此方法 并且必须返回属性列表

那么,
dir(t1)
怎么可能包含属性i,而
t1不包含属性呢?
而所有两个
dir(Test)
Test.\uuu dict\uuu
都包含属性i

这与回答您的问题的原因相同:

返回对象属性的行为很尴尬。
`dir(object)
反映了这种尴尬:

默认的dir()机制在不同的类型中表现不同 对象,因为它试图产生最相关的,而不是 完整,信息:

•如果对象是模块对象,则列表包含模块名称 模块的属性。
•如果对象是类型或类对象,则 列表包含其属性的名称,以及 其基础属性。
•否则,列表包含对象的 属性的名称,其类属性的名称,以及 递归地调用其类基类的属性

那么,你的问题的答案分为两部分:

1)
dir(t1)
给出了被视为对象属性的内容,但对象的真实名称空间(公开为
t1)。\uuuu dict\uuuu
不包含属性i,正如已经回答的那样,它实际上是一个类“atribute”

因此,两个实例t1t2的伪属性i看起来相等,因为表达式
t1.i
t2.i
实际上被评估为
Test.i

dir(t1)
dir(t2)
包含类的属性
Test.i

2) 表达式
t1.i
如何计算为
Test.i

因此(构成我答案的附加信息):

类实例有一个命名空间,该命名空间实现为 搜索属性引用的第一个位置。当 属性,并且实例的类具有 属性,则搜索将继续该类 属性


这意味着,当在对象的命名空间中找不到属性时,将在对象为实例的类的命名空间中搜索该属性。

这是一个类变量,正如您自己正确地说的那样-它属于该类,而不是该类的特定实例。请注意我的回答。我明白了,但当“t2=Test()时”运行时,行“i=0”不会再次运行并重置i=0吗?@学生:不会。您的类只定义一次。每次初始化类的新实例时,
\uuuuuu init\uuuuu
中的内容都会运行。为什么希望该行再次运行?该类只创建一次(否则将非常无用,因为实例将属于不同的类!)。
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