流畅的python笔记(二十)属性描述符

本文深入探讨Python的描述符机制,展示了如何使用描述符进行属性验证和管理。通过LineItem类的多个版本,阐述了描述符的工作原理,包括覆盖型和非覆盖型描述符的区别。此外,还讨论了方法作为描述符的角色,以及描述符在类和实例属性之间的交互。文章提供了关于描述符使用的一些建议,强调了正确实现描述符以提高代码效率和数据安全性的重要性。

目录

前言

一、描述符示例:验证属性

LineItem类第三版:一个简单的描述符

LineItem类第四版:自动获取储存属性的名称

LineItem类第五版:一种新型描述符

二、覆盖型与非覆盖型描述符对比

覆盖型描述符

没有__get__方法的覆盖型描述符

非覆盖型描述符

在类中覆盖描述符

三、方法是描述符

四、描述符用法建议

五、描述符的文档字符串和覆盖删除操作


前言

描述符是对多个属性运用相同存取逻辑的一种方式。

        描述符是实现了特定协议的类,这个协议包括__get__、__set__和__delete__方法。property类实现了完整的描述符协议。描述符是python的独有特征,不仅在应用层使用,在语言的基础设施中也有用到。

一、描述符示例:验证属性

LineItem类第三版:一个简单的描述符

实现了__get__、__set__、__delete__方法的类是描述符。描述符的用法是,创建一个实例,作为另一个类的类属性。下面例子中,我们将定义一个Quantity描述符类,然后创建两个Quantity实例作为LineItem类的类属性,分别用于管理weight实例属性和price实例属性:

以下是本节常用术语定义:

  • 描述符类,实现描述符协议的类。比如Quantity。
  • 托管类,把描述符类的实例声明为类属性的类,比如LineItem类。
  • 描述符实例,描述符类的各个实例,声明为托管类的类属性。
  • 托管实例,托管类的实例,比如LineItem类的实例。
  • 储存属性,托管实例中存储自身托管属性的属性,比如LineItem实例的weight和price两个实例属性都是储存属性。
  • 托管属性,托管类中由描述符实例处理的公开属性,值存储在储存属性中。

下面是Quantity描述符类和新版LineItem类,用到两个Quantity实例:

  1.  描述符基于协议实现,无需继承某抽象基类。
  2.  Quantity实例中有个storage_name属性,这是托管实例中的储存属性的名称。
  3.  尝试为托管属性赋值时,会调用__set__方法。这里self是描述符实例(即LineItem.weight或LineItem.price),instance是托管实例(LineItem实例),value是要设定的值。
  4. 这里必须直接处理托管实例的__dict__属性,如果使用内置的setattr函数,会再次触发__set__方法,导致无限递归。
  5. 第一个描述符实例绑定给weight属性。
  6. 第二个描述符实例绑定给price属性。

该例中各个托管属性的名称和储存属性一样,而且读值方法不需要特殊的逻辑,所以Quantity类不需要定义__get__方法。

LineItem类第四版:自动获取储存属性的名称

  

如上图左边所示,我们在托管类的定义体中实例化描述符时要输入两次属性的名称,如果能像上图右边那样,自动获取储存属性的名称,即只输入一次,可以让代码更简便。

        为了避免在描述符声明语句中重复输入属性名,我们将为每个Quantity实例的storage_name属性生成一个独一无二的字符串。

 

 

  1. __counter是Quantity类的类属性,统计Quantity实例的数量。
  2. cls是Quantity类的引用。
  3. 每个描述符实例的storage_name属性都是独一无二的,因为其值由描述符类的名称和__counter类属性的当前值构成,中间以#号隔开,如_Quantity#0。
  4. 递增__counter类属性的值。
  5. 需要实现__get__方法,因为托管属性的名称与storage_name不同。
  6. 使用内置的getattr函数从instance中获取储存属性的值。
  7. 使用内置的setattr函数把值存储在instance中,此时储存属性的名称是生成的,即Quantity中的self.storage_name属性,与托管属性的名称weight或price不同了,即我们在托管实例中打了猴子补丁,动态生成了新的属性作为储存属性。
  8. 现在不用把托管属性的名称传给Quanti
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值