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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值