gpt4 book ai didi

python - python中的属性 "__class__"到底是什么

转载 作者:IT老高 更新时间:2023-10-28 22:04:42 28 4
gpt4 key购买 nike

我有一个关于 python 中的 __class__ 的问题。

文档说 __class__ 是类实例所属的类。于是我进行了一系列的实验:

class counter:
count = 0
def __init__(self):
self.__class__.count += 1

NewCounter1 = counter()
print NewCounter1.count #The result is 1
NewCounter2 = counter()
print NewCounter2.count #The result is 2
print NewCounter2.__class__.count is NewCounter2.count #result: True

一切顺利。

然后我输入代码如下:

NewCounter2.__class__.count = 3

print NewCounter1.count #result:3
print NewCounter1.__class__.count #result:3
print NewCounter2.count #result:3
print NewCounter2.__class__.count #result:3
print NewCounter2.__class__.count is NewCounter2.count #result: True

从上面的代码中,我认为可能 NewCounter1.count 等于 NewCounter1,或者 __class__.count,但是下面的代码让我感到惊讶:

NewCounter2.count = 5

print NewCounter1.count #result:3
print NewCounter1.__class__.count #result:3
print NewCounter2.count #result:5
print NewCounter2.__class__.count #result:3
print NewCounter2.__class__.count is NewCounter2.count #result: False

为什么 NewCounter2.count 发生了变化,但 NewCounter2.__class__.count 仍为 3?更重要的是,当我更改 NewCounter2.count 时,NewCounter2.__class__.count is NewCounter2.count 变成了 False__class__ 属性到底是什么?

最佳答案

"From codes above, I thought that maybe NewCounter1.count equals NewCounter1. _class_.count"

问题是,在你的问题中,这句话的那一刻,在唯一的说明之后:

NewCounter1 = counter()
NewCounter2 = counter()
NewCounter2.__class__.count = 3

创建了 NewCounter1NewCounter2
并修改了类属性counter.count
NewCounter1.countNewCounter2.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 来显示以响应指令。

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

所以,NewCounter1.count equals NewCounter1.__class__.count这里的意思是 NewCounter1.count 的 VALUE,即使这个并不真正存在,也是类属性 NewCounter1 的 VALUE。 .count。这里的“is”是英语动词,不是语言中测试两个对象身份的特征is,它的意思是'被认为有'

NewCounter2.__class__.count = 3执行时,只有类属性 counter.count 受到影响。 NewCounter1NewCounter2 的命名空间保持为空,并遵循相同的机制去类中查找 counter.count 的值。

.

最后,当NewCounter2.count = 5执行时,这一次在 NewCounter2 对象中创建了一个 INSTANCE 属性 count 作为字段,并且 'count' 出现在 NewCounter2 的命名空间中。
它不会覆盖任何内容,因为实例的 __dict__ 之前没有任何内容。
没有其他更改会影响 NewCounter1counter.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__ 无关。但是搜索属性的机制,而这种机制在被忽略时会产生误导。

关于python - python中的属性 "__class__"到底是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8060751/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com