面向对象(OOP:Object Oriented Programming)8 -- 综合运用:将链表封装成容器&自定义类实现property功能

涉及知识点:容器方法、链表、描述器、类装饰器、反射

面向对象高阶业务运用二:将链表封装成容器,实现负向索引操作。

跳转:python实现双向链表


面向对象高阶业务运用三:自定义Property类,实现property功能。

需求分析

property是一个数据描述器。从类A的属性name被装饰的流程进行逻辑推导:

  • 首先,@property装饰name -> 返回一个数据描述器property的实例,与标识符name绑定,原name方法成为property实例的一个动态属性;
  • 然后,@name.setter再次装饰第二个name,第一个name已经是property的实例了,装饰过后,第二个name方法再次成为property实例的第二个动态属性;
  • 最后,类A的name属性其实是被装饰两次后的一个数据描述器,这个数据描述器被动态绑定了访问和修改实例属性_name的两个方法。
class A:
    def __init__(self, name):
        self._name = name

    @property  # -> name=property(name)
    def name(self):
        print("I'm the property")
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @name.deleter
    def name(self):
        print('del name')
        del self._name

        
if __name__ == '__main__':
    a = A('Tom')
    print(a.__dict__, a.__class__.__dict__)
    print(a.name)
    a.name = 'hah'
    print(a.name)
    print(a.__dict__)
    del a.name
    print(a.__dict__)

小结: 由上述分析可知,类A实例化后,通过a.name访问实例属性_name时,因为类属性name是一个数据描述器,自动触发__get__方法,__get__内部调用了动态绑定的访问实例属性_name的第一个name方法;而通过a.name="Tom"修改实例属性_name时,触发__set__方法,__set__内部一定调用了被动态绑定的修改实例属性_name的第二个name方法。

代码实现

由上述分析,自定义Property数据描述器,初步实现property类功能代码如下:

class Property:
    def __init__(self, get_method):
        self.get_method = get_method
        self.set_method = None

    def __set__(self, instance, value):
        self.set_method(instance, value)

    def __get__(self, instance, owner):
        return self.get_method(instance)

    def setter(self, method):
        self.set_method = method
        return self


class A:
    def __init__(self, name, age):
        self._name = name
        self.__age = age

    @Property
    def age(self):
        print("I'm the Property")
        return self.__age

    @age.setter
    def age(self, value):
        self.__age = value


if __name__ == '__main__':
    a = A('Tom', 19)
    print('~~~~~~~~~自定义Property类测试~~~~~~~~~~~~~~~~')
    print(a.__dict__)
    print(a.age)
    a.age = 100
    print(a.age)
    print(a.__dict__)

执行结果:

{'_name': 'Tom', '_A__age': 19}  
I'm the Property  
19  
I'm the Property  
100  
{'_name': 'Tom', '_A__age': 100}  

欢迎留言交流、讨论,觉得不错可以点波关注哦…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个两个四个三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值