zoukankan      html  css  js  c++  java
  • python对象 属性访问优先级:object.name

    python对象 属性访问优先级:object.name

    1. object.__getattribute__(self, name)
    2. 类 中的 数据描述符
    3. object.__dict__.get(name) 自身属性字典
    4. object.__class__.__dict__.get(name) 类属性字典 / 非数据描述符
    5. object.__getattr__(name)
    • 描述符:定义了 __get__() 的 类 #没有定义,返回描述符(普通类)实例
    • 数据(覆盖型)描述符: 定义了 __set__() 或者 __delete__() 中一个以上

    类属性name如果是数据描述符,会截断 实例的属性访问和修改:

    ​ "self.name = value";就变成了name.__set__(self, ins, value)

    ​ "self.name";就变成了name.__get__(self, ins, ins.__class__ )

    • 定义 __delete__() 没定义 __set__(),在实例赋值时就会报错

    • 定义 __set__() 没定义 __delete__(),在实例删除 就会报错

    试验代码:

    # -*- coding: utf-8 -*-
    # author: willowj
    # date: 2018-01-03 21:32:50
    # py2.7
    
    class Descdata(object):
    
        def __init__(self, name=''):
            self.name = name
            self.value = 0
            # 常用dict,可根据不同的instance set不同的值,get 返回不同的值
            # 相当于给每一个实例绑定了一个值
    
        def __get__(self, instance, owner=None):
    
            print("Descdata:inst> %s__get__() is called---" % self.name,
                  instance, owner)
            return self.value
    
        def __set__(self, instance, value):
            print("Descdata:inst> %s __set__() is called---" % self.name,
                  instance, value)
            self.value = value
    
        def __delete__(self):
            print('Descdata inst %s: .__delete__---'% self.name)
            del self
    
    
    class Desc_not_data(object):
    
        def __init__(self, name='', value='as654'):
            self.name = name
            self.value = value
    
        def __get__(self, instance, owner=None):
            print("Desc_not_data:inst> %s__get__() is called---" % self.name,
                  instance, owner)
            return self.value
    
    
    class Base(object):
        def __getattribute__(self, *args, **kwargs):
            print("Base __getattribute__() is called")
            return object.__getattribute__(self, *args, **kwargs)
    
    
    class Test(Base):
        a = 'abc'
        d_d = Descdata(name='d_d') # 数据描述符,如果实例有同名属性 会拦截
    
        nd = Desc_not_data(name='nd') # 非数据描述符,如果实例有同名属性 不会拦截
        nd2 = Desc_not_data(name='nd2') # 非数据描述符,如果实例有同名属性 不会拦截
    
    
        def __init__(self, *args, **kwargs):
            self.d_d = 'Test_ins self d_d'
            #  if cls.d_d 是数据描述符,这里就是调用数据描述符的 __set__
            # 类属性name如果是数据描述符,会截断--实例ins: "self.name = value";
            # 要是定义了 __delete__ 没定义 __set__,在实例赋值时就会报错
            self.nd2 = 'Test_>nd2' # 优先于 非数据描述符
    
        def __getattribute__(self, *args, **kwargs):
            print("Test  __getattribute__() is called")
            return Base.__getattribute__(self, *args, **kwargs)
    
        def __getattr__(self, name):
            print("Test __getattr__() is called ")
            return name + " from __getattr__"
    
    
    q = Test() # __init__ : 赋值 数据描述符
    # ('Descdata:inst> d_d __set__() is called---', <__main__.Test object at 0x0000000002B69DD8>, 'Test_ins self d_d')
    
    print('-'*30,u'visit data descriptor')
    
    print 'q.d_d
    ', q.d_d, '
    '
    # ('------------------------------', u'visit data descriptor')
    # q.d_d
    # Test  __getattribute__() is called
    # Base __getattribute__() is called
    # ('Descdata:inst> d_d__get__() is called---', <__main__.Test object at 0x0000000002B69DD8>, <class '__main__.Test'>)
    # Test_ins self d_d
    
    print('-'*30,u'visit non data descriptor not overided by instance')
    
    print 'q.nd
    ', q.nd, '
    '
    # ('------------------------------', u'visit non data descriptor')
    # q.nd
    # Test  __getattribute__() is called
    # Base __getattribute__() is called
    # ('Desc_not_data:inst> nd__get__() is called---', <__main__.Test object at 0x0000000002B69DD8>, <class '__main__.Test'>)
    # as654
    print('-'*30,u'visit non data descriptor overided by instance')
    print 'q.nd2
    ', q.nd2, '
    '
    # ('------------------------------', u'visit non data descriptor overided by instance')
    # q.nd2
    # Test  __getattribute__() is called
    # Base __getattribute__() is called
    # Test_>nd2
    
    
    print('-'*30,u"visit  attr that not exist" )
    print 'q.nnnnnnnnnnnnn
    ', q.nnnnnnnnnnnnn, '
    '
    
    # ('------------------------------', u'visit  attr that not exist')
    # q.nnnnnnnnnnnnn
    # Test  __getattribute__() is called
    # Base __getattribute__() is called
    # Test __getattr__() is called
    # nnnnnnnnnnnnn from __getattr__
    
    
    print('
     q.__dict__')
    print q.__dict__
    #  q.__dict__
    # Test  __getattribute__() is called
    # Base __getattribute__() is called
    # {'nd2': 'Test_>nd2'}
    print('-'*30,'
    ',' Test.__dict__')
    a_dict_  = dict(Test.__dict__)
    for k in a_dict_:
        print k,' '*(20-len(k)),a_dict_[k]
    
    
    # ('------------------------------', '
    ', ' Test.__dict__')
    # a                     abc
    # __module__            __main__
    # nd                    <__main__.Desc_not_data object at 0x0000000002AA9DA0>
    # __getattribute__      <function __getattribute__ at 0x0000000002AF0048>
    # __getattr__           <function __getattr__ at 0x0000000002AF00B8>
    # d_d                   <__main__.Descdata object at 0x0000000002AA9D30>
    # nd2                   <__main__.Desc_not_data object at 0x0000000002AA9DD8>
    # __doc__               None
    # __init__              <function __init__ at 0x0000000002AB7F98>
    
    
    print('-'*30)
    
    print Test.__dict__['__getattribute__'] ,type(Test.__dict__['__getattribute__'])
    # <function __getattribute__ at 0x0000000002B74048> <type 'function'>
    

    推荐资料

    https://www.cnblogs.com/Jimmy1988/p/6808237.html

    https://www.zhihu.com/question/25391709/answer/30634637

    https://foofish.net/what-is-descriptor-in-python.html

    http://www.cnblogs.com/JohnABC/p/5685672.html

  • 相关阅读:
    〖Linux〗-- 复制、用户和组操作、权限更改
    〖Linux〗-- 文本结构和基本命令
    〖Demo〗-- ATM
    〖Python〗-- 脚本目录规范
    二、配置文件
    一、SpringBoot入门
    File--字节流--字符流
    File--字节流--字符流
    SpringBoot快速搭建流程
    SpringBoot快速搭建流程
  • 原文地址:https://www.cnblogs.com/willowj/p/8287933.html
Copyright © 2011-2022 走看看