python对象属性的访问顺序_python对象 属性访问优先级:object.name

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

object.__getattribute__(self, name)

类 中的 数据描述符

object.__dict__.get(name) 自身属性字典

object.__class__.__dict__.get(name) 类属性字典 / 非数据描述符

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>, '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>, )

# Test_ins self d_d

print('-'*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>, )

# as654

print('-'*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_>nd2

print('-'*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>

# __getattribute__

# __getattr__

# d_d <__main__.descdata object at>

# nd2 <__main__.desc_not_data object at>

# __doc__ None

# __init__

print('-'*30)

print Test.__dict__['__getattribute__'] ,type(Test.__dict__['__getattribute__'])

#

推荐资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值