python数据描述符_python学习之描述符

class Foo:

def __get__(self, instance, owner):

print('===>get方法')

def __set__(self, instance, value): #self相当于Foo对象,instance相当于b1实例对象,value等于10

print('===>set方法',instance,value)

instance.__dict__['x']=value #b1.__dict__

def __delete__(self, instance):

print('===>delete方法')

class Bar:

x=Foo() #在何地?这里定义了描述符对象(x被Foo代理)

def __init__(self,n):

self.x=n #b1.x=10

b1=Bar(10)

print(b1.__dict__)

b1.x=11111111111111111

print(b1.__dict__)

b1.y=11111111111111111111111111111111111111

print(b1.__dict__)

由Bar类产生的实例,对x属性的调用,全部都去找Foo类

4 注意事项:

一 描述符本身应该定义成新式类,被代理的类也应该是新式类

二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中

三 要严格遵循该优先级,优先级由高到底分别是

1.类属性

class Str:

def __get__(self, instance, owner):

print('Str调用')

def __set__(self, instance, value):

print('Str设置...')

def __delete__(self, instance):

print('Str删除...')

class People:

name=Str()

def __init__(self,name,age): #name被Str类代理,age被Int类代理,

self.name=name

self.age=age

#基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典

#那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错

People.name #恩,调用类属性name,本质就是在调用描述符Str,触发了__get__()

People.name='egon' #那赋值呢,我去,并没有触发__set__()

del People.name #赶紧试试del,我去,也没有触发__delete__()

#结论:描述符对类没有作用-------->傻逼到家的结论

'''

原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级

People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()

People.name='egon' #那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()

del People.name #同上

'''

2.数据描述符

class Str:

def __get__(self, instance, owner):

print('Str调用')

def __set__(self, instance, value):

print('Str设置...')

def __delete__(self, instance):

print('Str删除...')

class People:

name=Str()

def __init__(self,name,age): #name被Str类代理,age被Int类代理,

self.name=name

self.age=age

p1=People('egon',18)

#如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性

p1.name='egonnnnnn'

p1.name

print(p1.__dict__)#实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了

del p1.name

3.实例属性

class Foo:

def func(self):

print('我胡汉三又回来了')

f1=Foo()

f1.func() #调用类的方法,也可以说是调用非数据描述符

#函数是一个非数据描述符对象(一切皆对象么)

print(dir(Foo.func))

print(hasattr(Foo.func,'__set__'))

print(hasattr(Foo.func,'__get__'))

print(hasattr(Foo.func,'__delete__'))

#有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了

#笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么

#函数就是一个由非描述符类实例化得到的对象

#没错,字符串也一样

f1.func='这是实例属性啊'

print(f1.func)

del f1.func #删掉了非数据

4.非数据描述符

class Foo:

def __set__(self, instance, value):

print('set')

def __get__(self, instance, owner):

print('get')

class Room:

name=Foo()

def __init__(self,name,width,length):

self.name=name

self.width=width

self.length=length

#name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级

#对实例的属性操作,触发的都是描述符的

r1=Room('厕所',1,1)

r1.name

r1.name='厨房'

class Foo:

def __get__(self, instance, owner):

print('get')

class Room:

name=Foo()

def __init__(self,name,width,length):

self.name=name

self.width=width

self.length=length

#name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级

#对实例的属性操作,触发的都是实例自己的

r1=Room('厕所',1,1)

r1.name

r1.name='厨房'

5.找不到的属性触发__getattr__()

class Foo:

def func(self):

print('我胡汉三又回来了')

def __getattr__(self, item):

print('找不到了当然是来找我啦',item)

f1=Foo()

f1.xxxxxxxxxxx

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值