您的位置:首页 > 编程语言 > Python开发

18 What is the __dict__.__dict__attribute of a Python class

2016-12-08 15:31 405 查看

What is the
__dict__.__dict__
attribute of a Python class?

What is the __dict____dict__attribute of a Python class
problem

解释

实例中不存在__dict__的情况

__dict__不存储在实例上的原因

总结

code

参考网址

转载请标明出处(http://blog.csdn.net/lis_12/article/details/53519060)

problem

class Foo(object):
pass

>>>Foo.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Foo' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None})

>>>Foo.__dict__.__dict__
AttributeError: 'dictproxy' object has no attribute '__dict__'

>>>Foo.__dict__['__dict__']
<attribute '__dict__' of 'Foo' objects>


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__
的情况

默认情况下,一个空的类有三个描述符,

__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}


__dict__
不存储在实例上的原因

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)               #True


Foo.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


code

class A(object):
pass

a = A()
print 'type(a) = ',type(a)           #type(a) =  <class '__main__.A'>
print 'type(A) = ',type(A)           #type(A) =  <type 'type'>

print 'a.__dict__ = ',a.__dict__     #a.__dict__ =  {}
print 'A.__dict__ = ',A.__dict__     #{'__dict__': <attribute '__dict__' of 'A' objects>...
#print 'type.__dict__ = ',type.__dict__,'\n'

print 'type(a.__dict__)    = ',type(a.__dict__)
print 'type(A.__dict__)    = ',type(A.__dict__)
print 'type(type.__dict__) = ',type(type.__dict__),'\n'
'''
result:
type(a.__dict__)    =  <type 'dict'>
type(A.__dict__)    =  <type 'dictproxy'>
type(type.__dict__) =  <type 'dictproxy'>
'''

print "A.__dict__['__dict__'] = ",A.__dict__['__dict__']
print "type.__dict__['__dict__'] = ",type.__dict__['__dict__'],'\n'

print "type(A.__dict__['__dict__']) = ",type(A.__dict__['__dict__'])
print "type(type.__dict__['__dict__']) = ",type(type.__dict__['__dict__']),'\n'
'''
result:
A.__dict__['__dict__']          =  <attribute '__dict__' of 'A' objects>
type.__dict__['__dict__']       =  <attribute '__dict__' of 'type' objects>

type(A.__dict__['__dict__'])    =  <type 'getset_descriptor'>
type(type.__dict__['__dict__']) =  <type 'getset_descriptor'>
'''

print a.__dict__ == A.__dict__['__dict__'].__get__(a)
print a.__dict__ == A.__dict__['__dict__'].__get__(a,type(a))

print A.__dict__ == type(A).__getattribute__(A, '__dict__')
print A.__dict__ == type(A).__dict__['__dict__'].__get__(A)
print A.__dict__ == type(A).__dict__['__dict__'].__get__(A,type(A))

print a.__dict__ == A.__getattribute__(a, '__dict__')
print a.__dict__ == type(A).__dict__['__dict__'].__get__(A)['__dict__'].__get__(a)
#上述都为True


参考网址

http://stackoverflow.com/questions/4877290/what-is-the-dict-dict-attribute-of-a-python-class

https://docs.python.org/2/library/functions.html?highlight=dictproxy

http://stackoverflow.com/questions/25440694/whats-the-purpose-of-dictproxy

http://blog.csdn.net/lis_12/article/details/53453665

http://blog.csdn.net/lis_12/article/details/53511300
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐