我对以下代码有一些意外的行为:
<td class="playerWinLeft alignleft"><div class="relative">a href="services.runescape.com/m=hiscore/a=13/ranking?category_type=0&table=0&page=1">2,715/a></div></td>
如您所见,我正在更改变量的实例版本,并获得预期的结果。但是当我将MyClass.Value更改为10时,我希望它能够更改所有实例的值。但也许我的理解不正确。
任何帮助都将深表感谢。
答案 0 :(得分:1)
首先,object1
和object2
都是MyClass
的实例,没有任何特定于实例的变量。然后你改变object1.value
。它仍然是MyClass
的成员,但是当你要求object1.value
时,你会得到6,因为一旦它看到它有自己的值,它就不会看MyClass
的值。这给出了迄今为止的预期行为。
当您将MyClass.value
更改为10时,只要您查找MyClass.value
,就会得到10.当您直接查找或通过object2
查找时,会发生这种情况。但是,object1
仍然有自己的value
,因为您将其设置为6.因此当您要求object1.value
时,它会在value
中查找object1
并且看到6.它没有注意到MyClass
的版本发生了变化。
object2
不会发生这种情况,因为它没有关联的value
;查询在object2
中失败,因此它会尝试查找object2.__class__.value
。由于object2
是MyClass
的实例,object2.__class__
为MyClass
,因此它为10。
如果你要说del object1.value
,那么查看object1.value
,你就可以从MyClass
得到10,就像object2
一样。
答案 1 :(得分:0)
在幕后发生的事情是,当您分配实例属性时,该实例的私人字典(__dict__
)会得到更新,但不会更新课程&#39; s __dict__
。前者优先查找所请求的属性,如果找不到它(在前几行,并且始终为object2
),则该类{{1用于查找属性。
具体做法是:
属性赋值和删除更新实例的字典,而不是类的字典。如果类具有
__dict__
或__setattr__()
方法,则调用此方法而不是更新实例字典直接。
(强调我的。来自the Python documentation on the standard type hierarchy in the data model;你需要找到小节&#34;类实例&#34;,第二段。它之前的段落处理实例属性查找顺序整个小节和之前的小节&#34;自定义类&#34;,可能很好阅读以获得概念;也许有几次,因为它有点浓缩。)
通常帮助我理解下面发生了什么,是打印相关实例,类和属性的ID和(在这种情况下)__delattr__()
属性。 id不是你看到同一个对象的真正保证,但在使用CPython时通常对我有用。
您的代码,已调整为打印此代码:
__dict__
和我得到的输出(为了阅读舒适而添加了一些额外的换行符和空格):
from __future__ import print_function
class MyClass(object):
value = 5
object1 = MyClass()
object2 = MyClass()
print(object1.value, id(object1.value), object1.__dict__)
print(object2.value, id(object2.value), object2.__dict__)
print(MyClass.value, id(MyClass.value), MyClass.__dict__)
object1.value = 6
print(object1.value, id(object1.value), object1.__dict__)
print(object2.value, id(object2.value), object2.__dict__)
print(MyClass.value, id(MyClass.value), MyClass.__dict__)
MyClass.value = 10
print(object1.value, id(object1.value), object1.__dict__)
print(object2.value, id(object2.value), object2.__dict__)
print(MyClass.value, id(MyClass.value), MyClass.__dict__)
每个运行和系统的ID都会有所不同,而且在这里方便5 4325640816 {}
5 4325640816 {}
5 4325640816 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__module__': '__main__', 'value': 5}
6 4325640848 {'value': 6}
5 4325640816 {}
5 4325640816 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__module__': '__main__', 'value': 5}
6 4325640848 {'value': 6}
10 4325640976 {}
10 4325640976 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__module__': '__main__', 'value': 10}
始终打印在'value'
,但您可以看到哪些属性发生了变化,哪些属性实际上是相同的,以及<{1}}属性已更新。
(注意:不自行修改MyClass.__dict__
属性。一般情况下,不要以任何方式使用它,不要从中读取。请使用其他内置方法和函数处理。)