1

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

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

0
1
1

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

4

3 回答 3

2

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

您必须创建i一个实例变量:

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

    def add(self):
        self.i += 1
于 2013-03-17T22:12:32.273 回答
1

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

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

Python 自动将实例作为参数self传递给方法。因此,在该方法中,您可以将实例的属性称为self.i.

于 2013-03-17T22:12:39.853 回答
0
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

.

对象名称__dict__的属性是表示该对象名称空间的字典,即包含该对象的属性。

此外,我们还有:

目录([对象])

如果对象有一个名为 的方法__dir__(),该方法将被调用并且必须返回属性列表。

那么,它怎么可能dir(t1)包含属性it1.__dict__没有呢?虽然所有两个dir(Test)Test.__dict__包含属性i ?

.

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

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

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

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

.

然后,您的问题的答案分为两部分:

1)dir(t1)给出了被认为是对象的属性,但对象的 REAL NAMESPACE,暴露为t1.__dict__不包含属性i,正如已经回答的那样,它实际上是一个类的属性。

因此,两个实例t1t2的伪属性i看起来相等,因为表达式and实际上被评估为,与包含类的属性的 方式相同 。t1.it2.iTest.i
dir(t1)dir(t2)Test.i

2) 表达式如何t1.i计算为Test.i??
因此(这构成了我的答案的附加信息):

类实例有一个作为字典实现的命名空间,这是搜索属性引用的第一个位置。如果在那里找不到属性,并且实例的类具有该名称的属性,则继续搜索类属性。

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

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

于 2013-03-17T22:59:45.827 回答