美文网首页
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