世界上的属性是“__ class __”在python [英] What in the world is the attribute "__class__" in python
问题描述
我有一个关于 __ class __
在python中的问题。
文档说, __class __
是类实例所属的类。所以我进行了一系列的实验:
类计数器:
count = 0
def __init __ ):
self .__ class __。count + = 1
NewCounter1 = counter()
print NewCounter1.count#结果为1
NewCounter2 = counter b $ b print NewCounter2.count#结果是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
equals 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是NewCounter2.count
成为 False
。世界上的属性 __ class __
?
从上面的代码,我认为也许NewCounter1.count等于NewCounter1。_class_.count
问题是,
NewCounter1 = counter()
NewCounter2 = counter()
NewCounter2 .__ class __。count = 3
/ strong>和 NewCounter2
并修改了类属性 counter.count ,
没有对象 NewCounter1.count 也不是 NewCounter2.count ,然后equals没有任何意义。
。
查看 NewCounter1 的创建以及之后:
类计数器:
count = 0
def __init __(self):
self .__ class __。count + = 1
print 'counter.count BEFORE ==',counter.count#结果是0
NewCounter1 = counter()
print'\\\
NewCounter1 .__ dict__ ==',NewCounter1 .__ dict__#结果是{}
print'NewCounter1.count ==',NewCounter1.count#结果是1
print'counter.count AFTER ==',counter.count#结果是1
NewCounter ._ dict _ 是实例的命名空间 NewCounter1
打印NewCounter1.count
打印与相同的打印计数器
然而,'count'(字符串'count')不在 NewCounter1 的命名空间中,也就是说没有属性 count 在创建的实例的命名空间中!
如何实现?
这是因为实例创建时没有赋值给'count' NewCounter1 中的 _ init _
- >没有真正创建任何属性表示不创建INSTANCE属性。
结果是,当指令
打印'NewCounter1.count =='时,NewCounter1.count
被评估,解释器在 NewCounter1 的命名空间中找不到实例属性,然后转到实例的类以搜索键'count'在这个类的命名空间;在其中找到count作为CLASS属性的键,并且可以将对象的 counter.count 作为VALUE来显示以响应该指令。
类实例具有实现为字典的命名空间,它是搜索属性引用的第一个位置
。当在那里没有找到
属性,并且实例的类具有该名称的
属性时,搜索继续使用类
属性。
http://docs.python.org/reference/datamodel.html#标准类型层次结构
因此,
NewCounter1.count等于NewCounter1 .__ class__。 count
这里意味着NewCounter1.count的VALUE(即使这个值不真的存在)也是类属性 NewCounter1的VALUE。 类 .count 。这里的是是英语动词,而不是测试两个对象的身份的语言的 ,这意味着被认为有
当执行
NewCounter2 .__ class __。count = 3
时,只会影响类属性 counter.count 。 NewCounter1 和 NewCounter2 的名称空间保持为空,并且使用类别查找 counter.count 的值的机制是相同的。
。
最后,当
NewCounter2.count = 5
被执行,这次在 NewCounter2 对象中创建一个INSTANCE属性计数作为一个字段,并且 NewCounter2 strong>。
它不会覆盖任何内容,因为实例的__ dict __
中没有任何内容。 NewCounter1 和 counter.count
以下代码更明确地显示执行期间的基础事件:
from itertools import islice
类计数器:
count = 0
def __init __ ):
print('| counter.count first ==%d at%d\\\
'
'| 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\\\
'
'| self.count second ==%d at%d\\\
'
'| id(counter)==%d id(self)==%d')\
%(counter.count,id(counter.count),
self.count,id(self.count),
id(counter),id(self))
$ b b
def display(* li):
it = iter(li)
for ch:
nn = .lstrip('\\\
')))*'\\\
'
x = it.next()
print'%s ==%s%s'%(ch,x,如果'__dict__'在ch else'at'+ str(id(x)))
显示('counter.count AT START',counter.count)
print('\\\
\\\
----- C1 = counter()-------------------- ----')
C1 = counter()
display('C1 .__ dict __',C1 .__ dict__,
'C1.count',C1.count,
' \\\
counter.count',counter.count)
print('\\\
\\\
----- C2 = counter()-------- ----------------')
C2 = counter()
print('---------------- ---------------------------')
显示('C1 .__ dict __',C1 .__ dict__,
' C2 .__ dict __',C2 .__ dict__,
'C1.count',C1.count,
'C2.count',C2.count,
'C1 .__ class __ count。 .__ class __。count,
'C2 .__ class __。count',C2 .__ class __ count,
'\\\
counter.count',counter.count)
$ b b print'\\\
\\\
------- C2 .__ class __。count = 3 ------------------------ \\\
'
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,
'\\\
counter.count',counter.count)
print'\\\
\\\
------- C2 .count = 5 ------------------------ \\\
'
C2.count = 5
显示('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,
'\\\
counter.count',counter.count )
结果
code> 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在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 __
,而是搜索属性的机制,在被忽略时具有误导性。I have a question about
__class__
in python.The documentation says that
__class__
is the class to which a class instance belongs. So I conducted a series of experiments: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
Everything goes well.
Then I enter code as follows:
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
From the code above, I thought that maybe
NewCounter1.count
equalsNewCounter1
, or__class__.count
, but the following code surprised me: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
Why has
NewCounter2.count
changed butNewCounter2.__class__.count
remained at 3? What's more, when I changedNewCounter2.count
,NewCounter2.__class__.count is NewCounter2.count
becameFalse
. What in the world is the attribute__class__
?解决方案"From codes above, I thought that maybe NewCounter1.count equals NewCounter1. _class_.count"
The problem is that at the moment of this sentence in your question, after the only instructions:
NewCounter1 = counter() NewCounter2 = counter() NewCounter2.__class__.count = 3
having created NewCounter1 and NewCounter2
and having modified the class attribute counter.count,
there are no objects NewCounter1.count nor NewCounter2.count in existence, and then "equals" has no real meaning..
See the creation of NewCounter1 and just after:
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_ is the namespace of the instance NewCounter1
print NewCounter1.count
prints the same asprint counter.count
However, 'count' (the string 'count') isn't in the namespace of NewCounter1, that is to say there is no attribute count in the namespace of the created instance !How is it possible ?
That's because the instance is created without assignement to a 'count' identifier inside the _init_
-> there is no real creation of any attribute as a field in NewCounter1, that is to say no creation of INSTANCE attribute.The consequence is that when the instruction
print 'NewCounter1.count ==',NewCounter1.count
is evaluated, the interpreter doesn't find an instance attribute in the NewCounter1 's namespace, and then goes to the class of the instance to search for the key 'count' in this class's namespace; there it finds 'count' as a key of a CLASS attribute and can take the VALUE of the object counter.count as a VALUE to display in response to the instruction.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
So,
NewCounter1.count equals NewCounter1.__class__.count
here means that the VALUE for NewCounter1.count, even if this one doesn't really exist, is the VALUE of the class attribute NewCounter1. class.count. Here "is" is the english verb, not the feature is of the language that tests the identities of two objects, and it means 'is considered to have 'When
NewCounter2.__class__.count = 3
is executed, only the class attribute counter.count is affected. The namespaces of NewCounter1 and NewCounter2 remain empty and the same mechanism of going to the class to find the value of counter.count is followed..
At the end, when
NewCounter2.count = 5
is executed , this time an INSTANCE attribute count is created as a field in the NewCounter2 object and 'count' appears in the namespace of NewCounter2 .
It doesn't overwrite anything, because there was nothing preceding in the instance's__dict__
No other change affects NewCounter1 and counter.countThe following code shows more explicitly the underlying events during execution:
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)
result
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
.
An interesting thing to do is to add an instruction
self.count = counter.count
BEFORE the line
self.__class__.count += 1 # <<=====
to observe the changing of results.
In conclusion, the point wasn't concerning
__class__
but the mechanism of searching an attribute , and this mechanism is misleading when ignored.这篇关于世界上的属性是“__ class __”在python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!