python笔记63 - __get__ 描述器(descriptor)学习

前言

描述器定义
描述器是一个类的类属性是另一个类的实例,另一个类中实现了__set____delete____get__方法之一。
如有两个类A,B,类A中实现__set____delete____get__方法之一。类B中的一个属性为类A的实例

描述器(descriptor)

描述器会用到三个魔术方法__get__(),   __set__() ,__delete__()
方法使用如下:

  • object.__get__(self,instance,owner)

  • object.__set__(self,instance,value)

  • object.__delete__(self,instance)

self指当前实例,调用者。instance是owner的实例。owner是属性所属的类。

先看一段代码,B类中的类属性a是A类的实例A()

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class A(object):

count = 0

def __init__(self):
self.name = "yoyo"
self.age = 18

def start(self):
print("start1111111")

class B(object):
a = A()

def __init__(self):
self.colour = 'red'
self.weight = 20

print(B.a.name)
b = B()
print(b.a.name)

上面的代码满足了第一个条件:一个类的类属性是另一个类的实例。
接着再第一个类A里面添加一个__get__()方法

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class A(object):

count = 0

def __init__(self):
self.name = "yoyo"
self.age = 18

def start(self):
print("start1111111")

def __get__(self, instance, owner):
print('{}{}{}'.format(self, instance, owner))

class B(object):
a = A()

def __init__(self):
self.colour = 'red'
self.weight = 20

print(B.a.name)
b = B()
print(b.a.name)

上面的代码运行就会抛AttributeError异常,出现错误的原因是:类A中定义__get__方法,那么类A就是描述器,原因是和类A中的__get__方法没return返回值

加上·return self `后

class A(object):

count = 0

def __init__(self):
self.name = "yoyo"
self.age = 18

def start(self):
print("start1111111")

def __get__(self, instance, owner):
# self指当前实例,调用者。Instance是owner的实例。Owner是属性所属的类。print('{}{}{}'.format(self, instance, owner))
return self

class B(object):
a = A()

def __init__(self):
self.colour = 'red'
self.weight = 20

print(B.a.name)
b = B()
print(b.a.name)

运行结果

<__main__.A object at 0x000002027F9696A0>None<class '__main__.B'>
yoyo
<__main__.A object at 0x000002027F9696A0><__main__.B object at 0x000002027F969748><class '__main__.B'>
yoyo

B.a.name调用的时候,B类没有实例,所以instance实例为None

实例属性不调用描述器

如果B类的实例属性self.a是A的实例,此时不会触发A类__get__方法

class A(object):

count = 0

def __init__(self):
self.name = "yoyo"
self.age = 18

def start(self):
print("start1111111")

def __get__(self, instance, owner):
print('{}{}{}'.format(self, instance, owner))
return self

class B(object):
# a = A()

def __init__(self):
self.a = A()
self.colour = 'red'
self.weight = 20

b = B()
print(b.a.name)

运行结果:yoyo
此时不满足描述器的使用条件,不会触发

参考资料:https://www.cnblogs.com/wangchunli-blogs/p/9949863.html
参考资料:https://www.cnblogs.com/andy1031/p/10923834.html

(0)

相关推荐

  • 关于def __init__(self)的一些知识点

    def __init__(self)在Python里面很常见,Python中的self在Python中的类Class的代码中,常看到函数中的第一个参数,都是self.以及Class中的函数里面,访问对 ...

  • 【python笔记】python java 语法,对比学习

    【python笔记】python java 语法,对比学习

  • python笔记35-装饰器

    前言 python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象. 很多python初学者学到面向对象类和方法是一道大坎,那么p ...

  • python笔记59-类里面的__getattribute__属性拦截器

    前言 写了一个类,类里面写了几个方法,在调用方法的时候,希望能打印出调用了哪个方法,方便快速定位问题,于是可以用类里面的getattribute属性拦截器. python的类默认都继承了object类 ...

  • python笔记61 - __getitem__ 方法学习与使用

    前言 如果在类中定义了__getitem__()方法,那么他的实例对象(假设为P)就可以这样P[key]取值. 当实例对象做P[key]运算时,就会调用类中的__getitem__()方法. __ge ...

  • python笔记61 - __getattr__ 属性查找学习与使用

    前言 object 类里面有个 __getattribute__ 方法,作用是类实例化调用属性和方法的时候都会调用一次,返回该类的属性. 如果调用的属性没有,会抛出 AttributeError 异常 ...

  • Python 中的函数装饰器和闭包

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回, ...

  • 完整版Python笔记|超级有用

    完整版Python笔记|超级有用

  • 看贴笔记(定窑X166--茶器)

    真正的藏家是由眼力.藏品.知识三点作支撑! 关注<宋元瓷器>,为你打开收藏的天空:本平台向你提供如下内容: 发文1:看帖笔记,老窑瓷器系列知识普及. 发文2:一真一假说瓷器. 发文3:小视 ...

  • 看贴笔记(定窑X167--茶器)

    真正的藏家是由眼力.藏品.知识三点作支撑! 关注<宋元瓷器>,为你打开收藏的天空:本平台向你提供如下内容: 发文1:看帖笔记,老窑瓷器系列知识普及. 发文2:一真一假说瓷器. 发文3:小视 ...