世界上的属性是“__ class __”在python [英] What in the world is the attribute "__class__" in python

查看:85
本文介绍了世界上的属性是“__ class __”在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 equals NewCounter1, 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 but NewCounter2.__class__.count remained at 3? What's more, when I changed NewCounter2.count, NewCounter2.__class__.count is NewCounter2.count became False. 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 as print 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.count

The 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆