python描述器descriptor_【数据挖掘】Python的描述器

01

背景

很多Python库中都会出现描述器(descriptor)的身影,Python内置的staticmethod, classmethod, property,super

等方法也都是描述器。了解描述器协议对于我们理解这些对象的行为会有很大帮助。

02

定义

通常,描述符是具有描述符协议中方法之一的属性值。这些方法是get(),set()和delete()。如果为属性定义了那些方法中的任何一种,则称其为描述符。

如果一个对象定义了以下三个方法中的任意一个,那么这个对象就可以被称之为描述器:

__set__(**)

__get__(**)

__delete__(**)

03

分类

如果对象定义set()或delete(),则将其视为数据描述符。仅定义get()的描述符称为非数据描述符(它们通常用于方法,但也可以用于其他用途)。

描述器又可分为数据描述器(data descriptor)和非数据描述器(non-data descriptor),只有*get*

方法的对象被称为非数据描述器(non-data desriptor),其他的都称为数据描述器(data descriptor)。

04

使用

下面通过一个例子来展示描述器是怎么使用的。

class PositiveNumber(object):

def __init__(self, name, value):

self.name = name

self._value = value

def __get__(self, obj, dtype):

return self._value

def __set__(self, obj, value):

if value < 0:

raise ValueError('Cannot be negative.')

self._value = value

if __name__ == '__main__':

number = PositiveNumber('number', 10)

上述代码中的number便是一个描述器。一般来说,描述器是作为另一个对象的属性来出现的:

class PositiveNumber(object):

def __init__(self, name, value):

self.name = name

self._value = value

def __get__(self, obj, dtype):

print("call `__get__` method")

print("obj : {}".format(obj))

print("dtype: {}".format(dtype))

return self._value

def __set__(self, obj, value):

if value < 0:

raise ValueError('Cannot be negative.')

print("call `__set__` method")

print("obj : {}".format(obj))

print("set price to {:d}".format(value))

self._value = value

def __delete__(self, obj):

print("call `__delete__` method")

print("obj : {}".format(obj))

print("delete object :{}".format(obj))

class Apple(object):

price = PositiveNumber('price', 0)

def __init__(self, price):

self.price = price

这样,描述器number作为Apple类的一个属性,在创建新的Apple实例apple=Apple(10)的时候,self.price = 10便会触发描述器的__set__方法, 监测price参数是否为正数,并在不符合条件的时候引发异常。

同样,当我们执行print(apple.price)时,dot操作符会触发描述器的__get__方法,执行删除操作的时候会触发描述器的__delete__方法。

这样,我们就通过定义描述器的方式,改变了对象的属性在赋值、删除和访问时的默认行为,描述器的功能正在于此。

05

扩展

1.Python内置的staticmethod, classmethod, property,super

等方法也都是描述器,具体的时候可以查看相应的文档

2.实例和类的dotted lookup 优先级有所不同,所以描述器在被类和实例调用时的行为也略有不同,参见Python文档。

参考资料

https://docs.python.org/zh-cn/3/howto/descriptor.html

https://zhuanlan.zhihu.com/p/52708890

往期推荐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值