最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

Python描述符的用法介绍(附示例)

来源:懂视网 责编:小采 时间:2020-11-27 14:20:26
文档

Python描述符的用法介绍(附示例)

Python描述符的用法介绍(附示例):本篇文章给大家带来的内容是关于Python描述符的用法介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的
推荐度:
导读Python描述符的用法介绍(附示例):本篇文章给大家带来的内容是关于Python描述符的用法介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的

本篇文章给大家带来的内容是关于Python描述符的用法介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的介绍

场景介绍

为了引入描述符的使用,我们先设计一个非常简单的类:

class Product():

 def __init__(self,name,quantity,price):
 self.name = name
 self.quantity = quantity
 self.price = price

这是一个商品类,存储该商品的名称,数量与价格。

对于一件商品,我们一般会期望它的数量和价格不会是负值,为了避免这种情况,我们可以在初始化的时候加一些判断,比如下面这样:

class Product():

 def __init__(self,name,quantity,price):
 self.name = name
 if quantity<0:
  raise ValueError('quantity must be >= 0')
 self.quantity = quantity
 if quantity<0:
  raise ValueError('price must be >= 0')
 self.price = price

但是这样还会有一个弊端就是这样的判断只是加在了初始化的时候,然后在之后对类的实例的属性进行赋值的时候还是无法保证赋的值是大于0 的

于是我们可以使用‘特性’来解决这个问题:

class Product():

 def __init__(self,name,quantity,price):
 self.name = name
 self.quantity = quantity
 self.price = price

 @property
 def quantity(self):
 return self._quantity

 @quantity.setter
 def quantity(self,value):
 if value < 0:
  raise ValueError('quantity must be >= 0')
 else:
  self._quantity = value

 @property
 def price(self):
 return self._price

 @price.setter
 def price(self, value):
 if value < 0:
  raise ValueError('price must be >= 0')
 else:
  self._price = value

book = Product('mybook',6,30)
print(book.quantity)

这里的@property和@quantity.setter是两个装饰器,它可以设置属性的读与写,就相当于读写属性,但其实是执行一个函数,具体有关特性的介绍,可以再自行查找,这里主要是为了引出描述符。

通过特性,可以完成为属性赋值时添加判断。但是当一个类中有更多的属性,很多属性同样需要添加非负数赋值的检查的时候,使用特性这种方式就会显得过于累赘,会有很多的代码重复,也会添加很多装饰器,这时就可以使用描述符来解决这个问题。

使用描述符

首先看一下描述符的概念

描述符就是一个“绑定行为“的对象属性,在描述符协议中,它可以通过方法充写属性的访问。这些方法有get(),set(),delete().如果这些方法中任何一个被定义在一个对象中,这个对象就是一个描述符

(这几个方法是特殊方法,双下划线由于转换未显示)

我们先把上文中的商品类按照使用描述符进行修改:

class NotNegative():
 def __init__(self,name):
 self.name = name

 def __set__(self, instance, value):
 if value < 0:
  raise ValueError(self.name+' must be >= 0')
 else:
  instance.__dict__[self.name] = value

class Product():
 quantity = NotNegative('quantity')
 price = NotNegative('price')

 def __init__(self,name,quantity,price):
 self.name = name
 self.quantity = quantity
 self.price = price

book = Product('mybook',2,5)

NotNegative是描述符类,它是Product类的类属性

在该例子中,如果执行book.quantity=3,解释器会先查找实例属性,发现有quantity属性,但是解释器又发现同样有一个类属性是描述符,于是解释器最终会选择走描述符这条路。然后因为是描述符,于是会执行描述符中的set特殊方法。

描述符中的set特殊方法的参数有为

self :是描述符实例

instance :是相当于例子中的实例book

value :就是要赋予的值

由于这些属性对于取值没有什么特殊的要求所以例子中没有实现get特殊方法。

get方法同样有3个参数self, instance, owner。self,instance与set中的相同,owner为例子中的Product类

接下来主要看一下描述符set方法中else部分进行的操作

instance.__dict__[self.name] = value

通过调用book实例的dict,直接为dict中的属性赋值,这也是参数中传入实例的一个重要原因。由于描述符对象是作为类属性存在,所以可能会有很多个该类的对象访问,为了防止属性的覆盖,直接存入实例的属性中是妥当的。但这里不能为属性赋值的方式,不然就会陷入死循环当中。

对于数据描述符与非数据描述符,一个类,如果只定义了 get() 方法,而没有定义 set(), delete() 方法,则认为是非数据描述符; 反之,则成为数据描述符。

最后,本文是对描述符的使用做了简单的介绍与讲解,如需更加深入了解可以参考《流畅的Python》属性描述符部分

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

Python描述符的用法介绍(附示例)

Python描述符的用法介绍(附示例):本篇文章给大家带来的内容是关于Python描述符的用法介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的
推荐度:
标签: 使用 介绍 详解
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top