转载请标明出处(http://blog.csdn.net/lis_12/article/details/53519060)
Foo.__dict__里面有'__dict__': <attribute '__dict__' of 'Foo' objects>属性,用Foo.__dict__.__dict__访问不到,用Foo.__dict__['__dict__']可以访问到,为什么呢?
搜索结果:stackoverflow解释链接,本文也是基于stackoverflow的解释,另外本文不考虑没有__dict__属性的实例。为了更好的理解本文,建议学习描述符…
Foo.__dict__.__dict__和Foo.__dict__['__dict__']是不一样的。
Foo.__dict__.__dict__ :根本就不存在Foo.__dict__['__dict__'] :用来存储Foo实例的__dict__属性。实例
实例会创建一个单独的dict对象来存储实例的属性,实例的__dict__存储在实例对应的类上,即type(实例)上。
instance.__dict__可以从type(instance).__dict__['__dict__']中获取;
因为type(instance).__dict__['__dict__']为描述符,
所以instance.__dict__ = type(instance).__dict__['__dict__'].__get__(instance,type(instance))
t = Foo.__dict__['__dict__'] print '__get__' in dir(t) #True,说明Foo.__dict__['__dict__']是描述符 print type(t) #<type 'getset_descriptor'> f = Foo() print type(f.__dict__) #<type 'dict'> d = t.__get__(f,type(f)) #利用描述符对象获取实例的__dict__ print f.__dict__ is d #True,证明上述正确类,以类Foo为例,
Foo的__dict__属性没有存储在Foo上,而是存储在Foo对应的类上,即type(Foo)上。对于type(Foo)来说,Foo为type(Foo)的实例。
Foo.__dict__可以从type(Foo).__dict__['__dict__']中获取;
因为type(Foo).__dict__['__dict__']为描述符,
所以Foo.__dict__ = type(Foo).__dict__['__dict__'].__get__(Foo,type(Foo))
t = type(Foo).__dict__['__dict__'] print '__get__' in dir(t) #True,说明type(Foo).__dict__['__dict__']是描述符 print type(t) #<type 'getset_descriptor'> print type(Foo.__dict__) #<type 'dictproxy'>,与实例的__dict__属性不同 d = t.__get__(Foo) print Foo.__dict__ == d #True,值相等 print Foo.__dict__ is d #False,虽然值相等,但地址不同,猜想...d应该是Foo.__dict__的拷贝,知道的大神求指导类的__dict__属性不同于实例的__dict__属性。类的__dict__属性是一个特殊代理对象(dictproxy),只不过这个对象伪装成了字典,并且class.__dict__不允许更改和替换。
摘自官网的一句话:new-style classes use a dictproxy to prevent direct dictionary updates.
class A(object): pass print A.__dict__ #{'__dict__': <attribute '__dict__' of 'A' objects>... print type(A.__dict__) #<type 'dictproxy'> #不能重写A.__dict__ A.__dict__ = 1 #AttributeError: attribute '__dict__' of 'type' objects is not writable默认情况下,一个空的类有三个描述符,
__dict__,存储实例属性;__weakref__;__doc__如果定义了__slots__,__dict__和__weakref__两个属性就没有了,__slots__中出现的变量名称将会以类属性的形式存在。
class Foo(object): __slots__ = 'a','b' f = Foo() #print f.__dict__ #AttributeError: 'Foo' object has no attribute '__dict__' print Foo.__dict__ #{'a': <member 'a' of 'Foo' objects>, '__module__': '__main__', 'b': <member 'b' of 'Foo' objects>, '__slots__': ('a', 'b'), '__doc__': None}As it’s impossible for the __dict__ of instance to be stored in __dict__ of the instance, it is accessed through the descriptor protocol directly instead, and is stored in a special field in the instance.
原因:
The inconsistency that A.__dict__ is different from A.__dict__['__dict__'] is because the attribute __dict__ is, by exception, never looked up in vars(A), so what is true for it isn’t true for practically any other attribute you’d use. For example, A.__weakref__ is the same thing as A.__dict__['__weakref__']. If this inconsistency didn’t exist, using A.__dict__ would not work, and you’d have to always use vars(A) instead.
以类Foo为例,Foo.attr与Foo.__dict__['attr']不相等的情况:
Foo.__dict__ != Foo.__dict__['__dict__']
因为__dict__属性是个例外,Foo.__dict__并没有存储在Foo上,而是存储在type(Foo)上 。
Foo.__dict__ == type(Foo).__dict__['__dict__'].__get__(Foo)
如果attr为自定义的描述符对象,Foo.attr != Foo.__dict__['attr']
在属性访问时,如果被访问的属性为描述符,会自动调用描述符的__get__()方法,
所以Foo.attr == Foo.__dict__['attr'].__get__(None,Foo)
class d(object): def __get__(self,obj,type = None): return 1 class Foo(object): a = d() b = 1 def attr(self): pass '''attr为自定义方法,证明方法为描述符''' print '__get__' in dir(Foo.__dict__['attr']) #True print Foo.attr == Foo.__dict__['attr'] #False print Foo.attr == Foo.__dict__['attr'].__get__(None,Foo)#True '''自定义的描述符''' x = Foo.a y = Foo.__dict__['a'] print x == y #False print x == y.__get__(None,Foo) #TrueFoo.attr与Foo.__dict__['attr']相等的情况:
Foo.attr == Foo.__dict__['attr'],attr不是__dict__和自定义描述符.
print Foo.b == Foo.__dict__['b'] #True w = Foo.__dict__['__weakref__'] print '__get__' in dir(Foo.__weakref__) #True print Foo.__weakref__ == w #True,__weakref__不是自定义描述符 print Foo.__weakref__ == w.__get__(None,Foo) #True