博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python对象 属性访问优先级:object.name
阅读量:4964 次
发布时间:2019-06-12

本文共 4759 字,大约阅读时间需要 15 分钟。

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.7class 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 selfclass 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.valueclass 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\n', q.d_d, '\n'# ('------------------------------', 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>, 
)# Test_ins self d_dprint('-'*30,u'visit non data descriptor not overided by instance')print 'q.nd\n', q.nd, '\n'# ('------------------------------', 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>,
)# as654print('-'*30,u'visit non data descriptor overided by instance')print 'q.nd2\n', q.nd2, '\n'# ('------------------------------', u'visit non data descriptor overided by instance')# q.nd2# Test __getattribute__() is called# Base __getattribute__() is called# Test_>nd2print('-'*30,u"visit attr that not exist" )print 'q.nnnnnnnnnnnnn\n', q.nnnnnnnnnnnnn, '\n'# ('------------------------------', u'visit attr that not exist')# q.nnnnnnnnnnnnn# Test __getattribute__() is called# Base __getattribute__() is called# Test __getattr__() is called# nnnnnnnnnnnnn from __getattr__print('\n q.__dict__')print q.__dict__# q.__dict__# Test __getattribute__() is called# Base __getattribute__() is called# {'nd2': 'Test_>nd2'}print('-'*30,'\n',' Test.__dict__')a_dict_ = dict(Test.__dict__)for k in a_dict_: print k,' '*(20-len(k)),a_dict_[k]# ('------------------------------', '\n', ' Test.__dict__')# a abc# __module__ __main__# nd <__main__.Desc_not_data object at 0x0000000002AA9DA0># __getattribute__
# __getattr__
# d_d <__main__.Descdata object at 0x0000000002AA9D30># nd2 <__main__.Desc_not_data object at 0x0000000002AA9DD8># __doc__ None# __init__
print('-'*30)print Test.__dict__['__getattribute__'] ,type(Test.__dict__['__getattribute__'])#

推荐资料

转载于:https://www.cnblogs.com/willowj/p/8287933.html

你可能感兴趣的文章
Boosting(提升方法)之AdaBoost
查看>>
Binding object to winForm controller through VS2010 Designer(通过VS2010设计器将对象绑定到winForm控件上)...
查看>>
Spring Boot实战笔记(二)-- Spring常用配置(Scope、Spring EL和资源调用)
查看>>
SwaggerUI+SpringMVC——构建RestFul API的可视化界面
查看>>
springmvc怎么在启动时自己执行一个线程
查看>>
C# 通知机制 IObserver<T> 和 IObservable<T>
查看>>
Code of Conduct by jsFoundation
查看>>
C#小练习ⅲ
查看>>
电源防反接保护电路
查看>>
arraylist
查看>>
zoj 1649 Rescue (BFS)(转载)
查看>>
2124: 等差子序列 - BZOJ
查看>>
字符串匹配算法综述
查看>>
Linux centosVMware shell 管道符和作业控制、shell变量、环境变量配置文件
查看>>
【设计模式】工厂模式
查看>>
两个表格中数据不用是一一对应关系--来筛选不同数据,或者相同数据
查看>>
客户数据库出现大量cache buffer chains latch
查看>>
機械の総合病院 [MISSION LEVEL: C]
查看>>
实战练习细节(分行/拼接字符串/字符串转int/weak和copy)
查看>>
Strict Standards: Only variables should be passed by reference
查看>>