“根据上面的代码,我认为 NewCounter1.count 可能等于 NewCounter1._class_.count”
问题是,在你的问题中,这句话的那一刻,在唯一的说明之后:
NewCounter1 = counter()
NewCounter2 = counter()
NewCounter2.__class__.count = 3
已创建 NewCounter1 和 NewCounter2
并修改了类属性 counter.count,
NewCounter1.count 和 NewCounter2.count 对象都不存在,则 "equals" 没有实际意义。
.
查看 NewCounter1 及之后的创建:
class counter:
count = 0
def __init__(self):
self.__class__.count += 1
print 'counter.count BEFORE ==',counter.count # The result is 0
NewCounter1 = counter()
print '\nNewCounter1.__dict__ ==',NewCounter1.__dict__ # The result is {}
print 'NewCounter1.count ==',NewCounter1.count # The result is 1
print 'counter.count AFTER ==',counter.count # The result is 1
NewCounter._dict_ 是实例的命名空间NewCounter1
print NewCounter1.count 打印与print counter.count 相同
但是,'count'(字符串'count')不在NewCounter1的命名空间中,也就是说创建的命名空间中没有count属性实例 !
这怎么可能?
这是因为创建实例时没有分配给 _init_
内的“计数”标识符
-> NewCounter1中没有真正创建任何属性作为字段,也就是说没有创建INSTANCE属性。
后果就是当指令
print 'NewCounter1.count ==',NewCounter1.count
求值时,解释器在 NewCounter1 的命名空间中没有找到实例属性,然后去实例的类在该类的命名空间中搜索键“count”;在那里,它找到“count”作为 CLASS 属性的键,并且可以将对象 counter.count 的 VALUE 作为 VALUE 来显示以响应指令。
一个类实例有一个命名空间实现为字典,它是
搜索属性引用的第一个位置。当一个
在那里找不到属性,并且实例的类有
按该名称的属性,搜索继续类
属性。
http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy
所以,NewCounter1.count equals NewCounter1.__class__.count 这里的意思是 NewCounter1.count 的 VALUE,即使这个并不真正存在,也是类属性 NewCounter1 的 VALUE。 类.count。这里的“is”是英语动词,不是语言中测试两个对象身份的特征is,它的意思是'被认为有'
NewCounter2.__class__.count = 3 执行时,只影响类属性counter.count。 NewCounter1 和 NewCounter2 的命名空间保持为空,并遵循相同的机制去类中查找 counter.count 的值。
.
最后,当NewCounter2.count = 5被执行时,这一次实例属性count被创建为NewCounter2对象中的一个字段,并且'count'出现在NewCounter2 的命名空间。
它不会覆盖任何内容,因为实例的 __dict__
之前没有任何内容
没有其他更改会影响 NewCounter1 和 counter.count
以下代码更明确地显示了执行期间的底层事件:
from itertools import islice
class counter:
count = 0
def __init__(self):
print (' | counter.count first == %d at %d\n'
' | self.count first == %d at %d')\
% (counter.count,id(counter.count),
self.count,id(self.count))
self.__class__.count += 1 # <<=====
print (' | counter.count second == %d at %d\n'
' | self.count second == %d at %d\n'
' | id(counter) == %d id(self) == %d')\
% (counter.count,id(counter.count),
self.count,id(self.count),
id(counter),id(self))
def display(*li):
it = iter(li)
for ch in it:
nn = (len(ch)-len(ch.lstrip('\n')))*'\n'
x = it.next()
print '%s == %s %s' % (ch,x,'' if '__dict__' in ch else 'at '+str(id(x)))
display('counter.count AT START',counter.count)
print ('\n\n----- C1 = counter() ------------------------')
C1 = counter()
display('C1.__dict__',C1.__dict__,
'C1.count ',C1.count,
'\ncounter.count ',counter.count)
print ('\n\n----- C2 = counter() ------------------------')
C2 = counter()
print (' -------------------------------------------')
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
print '\n\n------- C2.__class__.count = 3 ------------------------\n'
C2.__class__.count = 3
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
print '\n\n------- C2.count = 5 ------------------------\n'
C2.count = 5
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
结果
counter.count AT START == 0 at 10021628
----- C1 = counter() ------------------------
| counter.count first == 0 at 10021628
| self.count first == 0 at 10021628
| counter.count second == 1 at 10021616
| self.count second == 1 at 10021616
| id(counter) == 11211248 id(self) == 18735712
C1.__dict__ == {}
C1.count == 1 at 10021616
counter.count == 1 at 10021616
----- C2 = counter() ------------------------
| counter.count first == 1 at 10021616
| self.count first == 1 at 10021616
| counter.count second == 2 at 10021604
| self.count second == 2 at 10021604
| id(counter) == 11211248 id(self) == 18736032
-------------------------------------------
C1.__dict__ == {}
C2.__dict__ == {}
C1.count == 2 at 10021604
C2.count == 2 at 10021604
C1.__class__.count == 2 at 10021604
C2.__class__.count == 2 at 10021604
counter.count == 2 at 10021604
------- C2.__class__.count = 3 ------------------------
C1.__dict__ == {}
C2.__dict__ == {}
C1.count == 3 at 10021592
C2.count == 3 at 10021592
C1.__class__.count == 3 at 10021592
C2.__class__.count == 3 at 10021592
counter.count == 3 at 10021592
------- C2.count = 5 ------------------------
C1.__dict__ == {}
C2.__dict__ == {'count': 5}
C1.count == 3 at 10021592
C2.count == 5 at 10021568
C1.__class__.count == 3 at 10021592
C2.__class__.count == 3 at 10021592
counter.count == 3 at 10021592
.
一个有趣的事情是添加指令
self.count = counter.count
行前
self.__class__.count += 1 # <<=====
观察结果的变化
.
总之,重点不在于__class__,而在于搜索属性的机制,而这种机制在被忽略时会产生误导。