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 classproblem
解释
实例中不存在__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
instanceto 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-classhttps://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
相关文章推荐
- Part 68 - What is the use of NonAction attribute in mvc
- What is the difference between @staticmethod and @classmethod in Python?
- Question 30: What is the order of destructor calls for an object of class Y inherited from class X that has an object of class A
- python - what is the method attribute
- 详解 Tomcat: The value for the useBean class attribute is invalid 问题
- What is the easiest way of getting OpenLayers to configure itself for printing?
- What Is the Purpose of This Book?
- The base class includes the field '...', but its type (...) is not compatible with the type of control (...)
- Tomcat 中 "The value for the useBean class attribute is invalid" 错误的排除
- Programming Basic--what is the output of the following code?
- The unique identifier of the win32 class is the class name
- AS.NET2.0 用户控件错误!!The base class includes the field 'MyControl_1', but its type (MyControl) is not compatible with the type of control (ASP.MyControl_ascx).
- tomcat 调试JSP 文件出错 value for the useBean class attribute is invalid
- org.apache.jasper.JasperException The value for the useBean class attribute class.MyBean is invalid.
- Problem 16 - What is the sum of the digits of the number 2^1000?
- What is the most important aspect of programming?
- What is the future of IBM's WebSphere ?
- What is the ARGB int encoding of pixels in Java's AWT?
- 关于Tomcat: The value for the useBean class attribute is invalid 错误提示的解决方案
- Question #49: What is the output of the program?