2019/11/26 03-描述器概念

在这里插入图片描述
描述器几乎支撑了整个python面向对象有三个方法依然跟实例有关
get,set__,delete,del留给析构函数了,这里只能用delete了
del(self)只能由一个参数
delete(self,item)这里就有两个参数

在这里插入图片描述
加个print看看到底谁调用谁
在这里插入图片描述
有几个参数,现在这么直接调用是不行的在这里插入图片描述
调用构造器了
在这里插入图片描述
24行就有输出的东西,这样类跟实例就建立关系了
在这里插入图片描述在这里插入图片描述在这里插入图片描述
打印出a说明确实是实例的
在这里插入图片描述
还有一种方式,下面是通过类属性按照顺序找到a的实例调用
在这里插入图片描述在这里插入图片描述
走到这里,instance是none,owner是B在这里插入图片描述在这里插入图片描述
再注释中间的在这里插入图片描述
B.x访问x=A()
在这里插入图片描述
就跑到这里打印自己self,就用到了repr格式打印在这里插入图片描述在这里插入图片描述
打印整个看看
在这里插入图片描述
调用a1是none,B.x返回的对象调用a1,get是拿东西,看你没return就出问题了
在这里插入图片描述
return self在这里插入图片描述
这样就没问题了
在这里插入图片描述
这个方法,需要在这里构建两个类,B类属性指向另一个类的实例,当你访问这个类属性,相当于在访问类的实例,访问这个实例的时候,如果提供了__get__方法,就回来访问这个方法,B.X就是这么触发的,B.X.A1等于对它的B.X的返回值进行访问,所以等于A()实例.a1
owner属主这边的访问才会触发这个方法,self是A的实例
在这里插入图片描述
再换一种写法,两次实例化
在这里插入图片描述
现在打开一下类属性
在这里插入图片描述
查看里面三个参数各是什么
在这里插入图片描述
如果使用B的实例来访问,这里就显示B的实例在这里插入图片描述
现在看到的就是描述器的get方法,需要有2个类构成,其中一个类的类属性必须是另一个类的实例,在那个类中还要提供__get__方法在这里插入图片描述
注释掉运行起来也没什么问题
在这里插入图片描述
加了这个其实提供了一种编程的手段,访问的时候加一道拦截,做一些相应的处理,比如在owner上加个类属性上去
在这里插入图片描述
你想要这个实例有什么能力,这个x就有什么能力,本来属性是1234,现在可以描述成一个实例,,类有多强大,这个属性有多强大在这里插入图片描述
查看一下set

set

在这里插入图片描述在这里插入图片描述在这里插入图片描述
没有走到set里面 在这里插入图片描述
B。x已经被覆盖掉了在这里插入图片描述
换一种方式试试,这样好像有效果在这里插入图片描述
进去了
在这里插入图片描述在这里插入图片描述
赋值即定义,查看下字典里到底是什么在这里插入图片描述
x:A100,代表还是A的实例在这里插入图片描述
这一覆盖就什么都没了在这里插入图片描述
已经不是A的实例了,就不能那个用A的get方法在这里插入图片描述
如果调用instance就是属主的实例也送进来
在这里插入图片描述
A实例self,属主实例instance,在这里插入图片描述
赋值成功,等于赋值给B.X的返回到a1属性,改成2,所以这里的X实例是没有变化的
在这里插入图片描述
把实例搞清楚就可以
在这里插入图片描述
试试删除delete
在这里插入图片描述
x确实被删掉了
在这里插入图片描述
确实能够删除在这里插入图片描述
这是对三个方法的简单尝试
在这里插入图片描述在这里插入图片描述
self在谁里面就是谁的实例
instance跟owner相关,owner是属性的所属类

在这里插入图片描述
B的实例在不在,都不影响A的实例进行访问,大不了instance没有在这里插入图片描述
加入了get方法在这里插入图片描述
定义了__get__,set,__delete__的这个类,称为描述器,对于类B或者类B的实例的x属性读取,称为对类A的实例的访问,就会调用__get__方法、
解决报错,get方法有返回值
在这里插入图片描述在这里插入图片描述在这里插入图片描述
试试用B的实例来访问
在这里插入图片描述
现在来访问看看,实例属性有没有就一目了然了
在这里插入图片描述
现在测的很清楚,看到的描述器效果,似乎在实例上复制,通过这样访问的方式,虽然可以访问到实例,但是根本就不会调用get和set方法
如果是使用b.x=就一定会触发get和set方法
描述器是两个类和实例在一起,很麻烦

在这里插入图片描述在这里插入图片描述
b.b是没法触发get方法的
在这里插入图片描述在这里插入图片描述
python中一个类,实现了get,set,,delete方法,其中的任意一个方法,就是描述器,但是一般都会有get方法,如果仅仅是get,就称为非数据描述器,如果实现了get方法之外的,set和delete 2个之一叫数据描述器
非数据描述器和数据描述器表现的状况是不一样的
如果一个类的类属性设置为描述器实例,那么它被称为owner属主

在这里插入图片描述
属性的访问顺序,如果写了getattribute,是它,如果允许采用默认顺序走,就是object,这时候的顺序就是先实例子弟,然后是类字典,往祖先类找,如果找到object都没有,就需要抛出异常了,如果实现了getattr魔术方法,就交给它,暂时不抛出属性异常,除非自己抛出异常,否则异常就没有了在这里插入图片描述
试试加了描述器会怎么样
X=A()访问到A里面

在这里插入图片描述
现在print(b.x)打印什么结果
现在这么说,描述器虽然加了,但是对于实例来讲,优先使用自己的字典
在这里插入图片描述
这样看看打印什么,访问的是A的这个实例在这里插入图片描述
只有非数据描述器,只有get,现在测试下来,B.x跟实例无关,该怎么去访问就去怎么访问,因为是描述器,就触发 了get方法,但是使用实例来访问优先使用自己的字典在这里插入图片描述
只要get+set/delete就变成数据描述器在这里插入图片描述
提示set属性没有设置,说明找到set上去了
在这里插入图片描述在这里插入图片描述在这里插入图片描述
打印这个字典做了几件事情在这里插入图片描述
先打印的这边
在这里插入图片描述
set方法里没有赋值,实例字典里现在是空的在这里插入图片描述在这里插入图片描述
多了set是数据描述器,有了数据描述器,跟刚才的方式有点不同,非数据描述器是优先使用了实例的字典里面的数据,如果有赋值语句会在自己的字典里有的(self.x=1000
如果有了非数据描述器,就不会通过self.x=1000这样的语句加进去

上面是数据描述器,self.x=setattr(self,’‘x’’),这两个一样,就试试self.dict[’‘x’’],(其实不推荐这么写)
这样就写进去了
在这里插入图片描述
如果是数据描述器,访问属性还是按照描述器的方式来找,数据描述器优先使用描述器的值在这里插入图片描述
访问属性还是按照描述器的方式来找,数据描述器优先使用描述器的值在这里插入图片描述
把set注释掉,试试打印多少在这里插入图片描述
**就变成2000了,当如果用非数据描述器,优先用实例自己的
**在这里插入图片描述如果用数据描述器,就无视字典,直接使用描述器的来访问在这里插入图片描述在这里插入图片描述
所谓的属性相同就是类属性和实例属性同名,访问的时候实例没有就看类有没有,然后用类访问实例,类没有实例就不能访问
以前是如果同名。实例访问肯定是实例字典优先,因为看的是自己的字典,使用了数据描述器情况就改变了
在这里插入图片描述
在这里插入图片描述
实例的__dict__优先于非数据描述器,数据描述其优先于实例的__dict__在这里插入图片描述在这里插入图片描述
描述器是由两个类和其中一个类实例来产生关系,下面从属主类里面,通过实例来访问,用类来get是可以的
在这里插入图片描述
B。x相当于直接访问类,直接把x覆盖了
在这里插入图片描述在这里插入图片描述
描述器影响了属性的搜索顺序,数据描述器比实例字典优先,但是一般getattribute要加入进来,但是一般getattr和get描述器不会混着用

可以从B的类来访问描述器,描述器少不了,get,set,delete
在这里插入图片描述在这里插入图片描述
可以动态把实例z属性塞进去,相当于在B实例上增加z属性在这里插入图片描述
z=1000该怎么访问怎么访问在这里插入图片描述
使用非属性访问方式在这里插入图片描述
不建议这么玩,除非特别明确,还是大部分使用属性
在这里插入图片描述
数据描述器的优先级是比较高的,只要对属性访问就在这里操作,如果使用非数据描述器,是低于属性字典的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值