- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个关于 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
创建了 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 来显示以响应指令。
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 受到影响。 NewCounter1 和 NewCounter2 的命名空间保持为空,并遵循相同的机制去类中查找 counter.count 的值。
.
最后,当NewCounter2.count = 5
执行时,这一次在 NewCounter2 对象中创建了一个 INSTANCE 属性 count 作为字段,并且 '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__
无关。但是搜索属性的机制,而这种机制在被忽略时会产生误导。
关于python - python中的属性 "__class__"到底是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8060751/
在 Python 的文档中 __class__被描述为一个属性。在对象中 type (元类),__class__似乎是一种方法。 如果我们这样做: >>> class Foo: pas
我有一系列的类,它们都继承自共享一个基类的几个可能的父类中的一个。每个类都有一个基于基类 parameters 的类作用域 Dict[str, object] parameters from copy
这个问题在这里已经有了答案: Why doesn't 2.__add__(3) work in Python? (2 个答案) 关闭 3 年前。 整数是唯一不支持.__class__操作的类型吗?例
我最近正在单步调试 CPython 源代码,特别是查看 symbol table entry编译期间的一个类。 我遇到了 typedef struct _symtable_entry 的以下条目结构:
我想测试一个对象是否是一个类的实例,并且只有这个类(没有子类)。我可以这样做: obj.__class__ == Foo obj.__class__ is Foo type(obj) == Foo t
有以下服务器代码(我正在定义一个继承自套接字的类,并尝试使用该类调用客户端套接字上的发送方法): import socket class LogSocket(socket.socket): d
python 依赖于 cell 中的 __class__ 变量来进行 super() 调用。它从第一个堆栈帧中的free 变量获取此单元格。 奇怪的是,这个变量不在 locals() 中,而是在您从
我对设置对象的属性和在对象的 __class__ 属性上设置属性之间的区别感到有点困惑。粗略地说,obj.attr 与 obj.__class__.attr。它们有什么区别? 前者是在一个实例上设置一
在 pinax Userdict.py 中: def __getitem__(self, key): if key in self.data: return s
这个问题在这里已经有了答案: How to avoid infinite recursion with super()? (1 个回答) 关闭 5 年前。 我在 WTForms 中处理继承。我有下一
Django 源代码: def new_method_proxy(func): def inner(self, *args): if self._wrapped is empt
使用 __class__ 在类中创建新实例是个好主意吗? 以下代码是执行此操作的示例: from collections import namedtuple _Position = namedtupl
我希望能够做到: >>> class a(str): ... pass ... >>> b = a() >>> b.__class__ = str Traceback (most recent
我有一个关于 python 中的 __class__ 的问题。 文档说 __class__ 是类实例所属的类。于是我进行了一系列的实验: class counter: count = 0
也许这是一个微不足道的问题。在 python 下,为什么 self.__class__.__bases__ 没有回溯到 object?我的只显示了类(class)之上的单亲 parent 的元组。 最
我创建了这样的类来解决签名和 feature_names 的问题: import copy from sklearn.feature_selection import VarianceTreshold
我已阅读 Why is Python 3.x's super() magic?并了解在方法中使用 super 或 __class__ 会自动为该方法创建一个 __class__ 单元格变量: clas
我需要从类中获取类名: class Cls: notation = None def __init__(self): notation = self.__class__
我试图通过从该类派生并覆盖/添加某些方法来扩展用 C 编写的模块类的功能*。 问题是他的模块创建了我试图在不同地方扩展的类的实例。因此,我需要创建一个转换方法,将模块提供的基类转换为我自己的具有附加功
class Foo: pass >>> f = test.Foo() 让我们看看类实例...... >>> dir(f) ['__add__', [__class__] ...] 哦哦!让我们看看
我是一名优秀的程序员,十分优秀!