美文网首页
Python Attribute Access Order

Python Attribute Access Order

作者: aihex | 来源:发表于2016-11-05 08:30 被阅读0次

@(Python)

data descriptor case

data descriptor is defined as having both _get_ and _set_ method

class descriptor(object):
    def __get__(self, obj, type=None):
        print('descriptor-get')
    def __set__(self, obj, value):
        print('descriptor-set')
class A(object):
    x = descriptor()
    def __getattr__(self, name):
        print('A-getattr')
    
a = A()

a.__dict__ # empty instance dictionary
-> {}

A.__dict__ # type dictionary has attribute 'x'
-> dict_proxy({'__dict__': <attribute '__dict__' of 'A' objects>,
            '__doc__': None,
            '__getattr__': <function __main__.__getattr__>,
            '__module__': '__main__',
            '__weakref__': <attribute '__weakref__' of 'A' objects>,
            'x': <__main__.descriptor at 0x1065fec10>})

a.x # data descriptor takes precedence
-> descriptor-get

A.x # visit descriptor from type or class
-> descriptor-get

del A.__dict__['x'] # disallow to del attributes in type dictionary
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-52-bc9fd0bf9cec> in <module>()
----> 1 del A.__dict__['x']

TypeError: 'dictproxy' object does not support item deletion

non-data descriptor case

non-data descriptor is defined as only having _get_ method

class descriptor(object):
    def __get__(self, obj, type=None):
        print('descriptor-get')
class A(object):
    x = descriptor()
    def __getattr__(self, name):
        print('A-getattr')
    
a = A()

a.x # non-data descriptor is used because there is no such attribute in instance dictionary
-> descriptor-get

A.x
-> descriptor-get

A.__dict__
-> dict_proxy({'__dict__': <attribute '__dict__' of 'A' objects>,
            '__doc__': None,
            '__getattr__': <function __main__.__getattr__>,
            '__module__': '__main__',
            '__weakref__': <attribute '__weakref__' of 'A' objects>,
            'x': <__main__.descriptor at 0x1066008d0>})

a.__dict__['x'] = 2 # set 'x' attribute into instance dictionary or a.x=2

a.x # instance dictionary takes precedence
-> 2

A.x
-> descriptor-get

_getattr_ as backup

class A(object):
    def __getattr__(self, name):
        print('A-getattr')
    
a = A()

a.x # __getattr__ is called when there is no 'x' in data descriptor, instance dictionary and non-data descriptor.
-> A-getattr
 
A.__dict__['x'] = 1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-66-72c8240053eb> in <module>()
----> 1 A.__dict__['x'] = 1

TypeError: 'dictproxy' object does not support item assignment


a.__dict__['x'] = 1 # or 

a.x # instance dictionary takes precedence to __getattr__
-> 1

del a.x

a.x
-> A-getattr

A.x = descriptor() # assign a non-data descriptor into type dictionary 

A.x
-> descriptor-get

a.x # instance dictionary takes precedence to such non-data descriptor
-> 1

del a.x

a.x # non-data descriptor takes precedence to __getattr__
-> descriptor-get

相关文章

网友评论

      本文标题:Python Attribute Access Order

      本文链接:https://www.haomeiwen.com/subject/ponwuttx.html