当前位置: 首页 > 面试题库 >

python中的“ __class__”属性到底是什么

通鸿风
2023-03-14
问题内容

__class__在python中有一个问题。

文档说这__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.countNewCounter2.__class__.count is NewCounter2.count变得False。世界到底是__class__什么?


问题答案:

“从以上代码中,我认为NewCounter1.count等于NewCounter1。class.count”

问题是,在您的问题中此句子出现时,仅在以下说明之后:

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

创建了 NewCounter1NewCounter2
修改了类属性 counter.count之后
不存在对象 NewCounter1.countNewCounter2.count ,因此 “等于” 没有实际意义。

请在之后查看 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. _字典 _是实例的名称空间 NewCounter1
print NewCounter1.count 打印一样print counter.count
。然而,“计数”(字符串“数”)是不是在命名空间 NewCounter1 ,也就是说没有属性 在命名空间创建的实例!

这怎么可能 ?

这是因为没有assignement到“计数”标识内部创建实例的 _INIT _
- >有任何属性作为一个字段没有真正的创造 NewCounter1 ,也就是说没有创建实例属性。

结果是,在
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 。这里的“是”是英语动词,不是该功能
测试两个对象的身份的语言,它的意思是“被认为具有”

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

最后,当NewCounter2.count = 5执行时,这一次将在INSTANCE属性 计数 中创建一个 NewCounter2
对象中的字段,并且“ 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 Bug Tracker中的此问题,该问题还抱怨该错

  • 问题内容: 我想使用作为我的单元测试的基本目录(创建很多文件)。此属性指向当前工作目录是否正确(例如,由“ cd”命令设置)? 问题答案: 这java是运行JVM的目录。不必位于用户的主目录中。它可以在用户有权运行Java的任何地方。 因此,如果你cd进入,然后运行你的程序,将是。 另一个属性指向用户目录。如或或。

  • 我想使用dir作为单元测试(创建大量文件)的基本dir。此属性指向当前工作目录(例如,由'cd'命令设置)是否正确?

  • 问题内容: 我不知道如何工作。 文档中有一些解释。例如,它们的意思是: 带有最终估算器的变换管线。 为了使我的问题更清楚,什么是?它们如何工作? 编辑 由于有了答案,我可以使我的问题更清楚: 当我调用管道并通过时,需要两个转换器和一个估计器,例如: 我叫这个怎么办? 我不知道估算器如何成为变压器以及如何装配变压器。 问题答案: *scikit-learn中的 *Transformer- 一些具有f

  • 本文向大家介绍python使用xpath中遇到: 到底是什么?,包括了python使用xpath中遇到: 到底是什么?的使用技巧和注意事项,需要的朋友参考一下 前言 大家在学习python爬虫的过程中,会发现一个问题,语法我看完了,说的也很详细,我也认真看了,爬虫还是不会写,或者没有思路,所以我的所有文章都会从实例的角度来解析一些常见的问题和报错。下面话不多说了,来一起看看详细的介绍吧。 Elem

  • 问题内容: 我只想知道 到底是 什么 意思 ?甚至在SO上也没有在官方文档中找到任何解释。 如果您能提供一些例子,我将非常高兴。 问题答案: 请参阅PEP 366 和导入系统参考文档: 提议的主要更改是引入了新的模块级别属性。如果存在,则相对导入将基于此属性而非模块属性。 和 * 应该设置模块的属性。它的值必须是字符串,但可以与其值相同。如果该属性设置为或丢失,则导入系统将使用更合适的值填充该属性