python描述符详解_python描述符详解

什么是描述符

官方的定义:描述符是一种具有“捆绑行为”的对象属性。访问(获取、设置和删除)它的属性时,实际是调用特殊的方法(_get_(),_set_(),_delete_())。也就是说,如果一个对象定义了这三种方法的任何一种,它就是一个描述符。

描述符的作用是用来代理一个类的属性,需要注意的是描述符不能定义在被使用类的构造函数中,只能定义为类的属性,它只属于类的,不属于实例,我们可以通过查看实例和类的字典来确认这一点。

描述符是实现大部分Python类特性中最底层的数据结构的实现手段,我们常使用的@classmethod、@staticmethd、@property、甚至是__slots__等属性都是通过描述符来实现的。它是很多高级库和框架的重要工具之一,是使用到装饰器或者元类的大型框架中的一个非常重要组件。

普通对象

示例

class Parent:

name = "parent"

class Son(Parent):

name = "son"

s = Son()

s.name = "other"

print(s.name)

------------------------------------------------------------------------

other

普通的python对象操作(增删改查)它的属性时,都是基于该对象的__dict__基础之上进行的。比如,上例中访问实例对象s的属性name: s.name的时候,查找顺序如下所示:

通过实例对象的__dict__属性访问: s.__dict__['name']

通过类型对象的__dict__属性访问: type(s).__dict__['name']等价于Son.__dict__['name']

通过父类对象的__dict__属性访问: s.__class__.__base__.__dict__['name']等价于Parent.__dict__['name']

类似地修改属性name的值也是通过__dict__的方式:

s.__dict__['name'] = 'zhangsan'

print s.name

------------------------------------------------------------------------

zhangsan

描述符

class Descriptor:

def __init__(self, name):

self.name = name

def __get__(self, instance, owner):

print("__get__")

print("instance:", instance)

print("owner:", owner)

return self.name

def __set__(self, instance, value):

print("__set__", instance, value)

self.name = value

class Man:

name = Descriptor("张三")

someone = Man()

print(someone.name)

---------------------------------------------------------------------

__get__

instance: <__main__.man object at>

owner:

张三

这里的Descriptor就是一个描述符,访问Man对象的name属性时不再是通过__dict__属性来访问,而是通过调用Descriptor的__get__方法获取,同样的道理,给name赋值的时候是通过调用__set__方法实现而不是通过__dict__属性。

通过__dict__赋值,点号取值

someone.__dict__['name'] = '李四'

print(someone.name)

-----------------------------------------------------------------------

__get__

instance: <__main__.man object at>

owner:

张三

通过点号赋值

someone.name = "王二"

print(someone.name)

------------------------------------------------------------------------

__set__ <__main__.man object at> 王二

__get__

instance: <__main__.man object at>

owner:

王二

类似地,删除属性的值也是通过调用__delete__方法完成的。

数据描述符和非数据描述符

一个类,如果只定义了__get__ 方法,而没有定义__set__, __delete__ 方法,则认为是非数据描述符;反之,则成为数据描述符。

实例属性和类属性优先级高于非数据描述符,但低于数据描述符。

class Descriptor:

def __init__(self, name):

self.name = name

def __get__(self, instance, owner):

print("__get__")

print("instance:", instance)

print("owner:", owner)

return self.name

class Man:

name = Descriptor("张三")

m = Man()

# 实例属性

print("1:", m.name)

m.name = "李四"

print("2:", m.name)

print("3", Man.name)

Man.name = "王二"

print("4", Man.name)

-----------------------------------------------------------------------

__get__

instance: <__main__.man object at>

owner:

1: 张三

2: 李四

__get__

instance: None

owner:

3 张三

4 王二

属性查询优先级

__getattribute__

数据描述符:由1触发调用,若人为的重载了该__getattribute__方法,可能会调职无法调用描述符

实例对象的字典

类的字典

非数据描述符

父类的字典

__getattr__方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值