优草派 > 问答 > Python

通过实例解析python描述符原理作用

作者:SONG_GLD     

Python中的描述符是一种特殊的对象,它可以被用来管理类属性的访问方式,并且可以通过多种方式进行自定义。描述符可以被用来实现各种行为,例如数据验证、类型转换、缓存等等。在本篇文章中,我们将通过实例来解析Python描述符的原理和作用。

1. 描述符的分类

在Python中,描述符可以被分为三种类型:数据描述符、非数据描述符和简单描述符。

1.1 数据描述符

数据描述符是指实现了以下三个方法中的至少一个的描述符:

- `__get__(self, instance, owner)`:用于获取属性的值,其中`instance`表示所属实例对象,`owner`表示所属类对象。

- `__set__(self, instance, value)`:用于设置属性的值,其中`instance`表示所属实例对象,`value`表示要设置的值。

- `__delete__(self, instance)`:用于删除属性,其中`instance`表示所属实例对象。

1.2 非数据描述符

非数据描述符是指没有实现以上三个方法中的任何一个方法的描述符。

1.3 简单描述符

简单描述符是指实现了`__get__()`方法的描述符,但没有实现`__set__()`和`__delete__()`方法。

2. 描述符在类中的应用

下面我们通过一个实例来说明描述符在类中的应用。

```python

class Desc:

def __get__(self, instance, owner):

print('Desc __get__ is called')

return instance._x

def __set__(self, instance, value):

print('Desc __set__ is called')

instance._x = value

class Foo:

d = Desc()

def __init__(self, x):

self._x = x

foo = Foo(10)

print(foo.d)

foo.d = 20

print(foo.d)

```

在这个例子中,我们定义了一个名为`Desc`的描述符类和一个名为`Foo`的类。在`Foo`类中,我们定义了一个名为`d`的类属性,并将其设置为`Desc()`,这意味着`d`是一个数据描述符。在`Desc`类中,我们实现了`__get__()`和`__set__()`方法,并分别输出了一行信息。

在实例化`Foo`类后,我们访问了`foo.d`属性,并输出了`Desc __get__ is called`信息。这是因为我们实现了`__get__()`方法,所以当我们访问`foo.d`属性时,Python会自动调用`Desc`类中的`__get__()`方法。接着,我们将`foo.d`属性设置为20,并输出了`Desc __set__ is called`信息。这是因为我们实现了`__set__()`方法,所以当我们设置`foo.d`属性时,Python会自动调用`Desc`类中的`__set__()`方法。

3. 描述符在属性访问中的应用

下面我们通过另一个实例来说明描述符在属性访问中的应用。

```python

class Desc:

def __get__(self, instance, owner):

print('Desc __get__ is called')

return instance._x

def __set__(self, instance, value):

print('Desc __set__ is called')

instance._x = value

class Foo:

def __init__(self, x):

self._x = x

d = Desc()

foo = Foo(10)

print(foo.d)

foo.d = 20

print(foo.d)

```

在这个例子中,我们定义了一个名为`Desc`的描述符类和一个名为`Foo`的类。在`Foo`类中,我们定义了一个名为`d`的类属性,并将其设置为`Desc()`,这意味着`d`是一个数据描述符。在`Desc`类中,我们实现了`__get__()`和`__set__()`方法,并分别输出了一行信息。

在实例化`Foo`类后,我们访问了`foo.d`属性,并输出了`Desc __get__ is called`信息。这是因为我们实现了`__get__()`方法,所以当我们访问`foo.d`属性时,Python会自动调用`Desc`类中的`__get__()`方法。接着,我们将`foo.d`属性设置为20,并输出了`Desc __set__ is called`信息。这是因为我们实现了`__set__()`方法,所以当我们设置`foo.d`属性时,Python会自动调用`Desc`类中的`__set__()`方法。

4. 描述符在属性访问中的优先级

在Python中,当一个类属性同时存在数据描述符和实例属性时,数据描述符会优先于实例属性。

```python

class Desc:

def __get__(self, instance, owner):

print('Desc __get__ is called')

return instance._x

def __set__(self, instance, value):

print('Desc __set__ is called')

instance._x = value

class Foo:

d = Desc()

def __init__(self, x):

self._x = x

foo = Foo(10)

print(foo.d)

foo.d = 20

print(foo.d)

foo.__dict__['d'] = 30

print(foo.d)

```

在这个例子中,我们定义了一个名为`Desc`的描述符类和一个名为`Foo`的类。在`Foo`类中,我们定义了一个名为`d`的类属性,并将其设置为`Desc()`,这意味着`d`是一个数据描述符。在`Desc`类中,我们实现了`__get__()`和`__set__()`方法,并分别输出了一行信息。

在实例化`Foo`类后,我们访问了`foo.d`属性,并输出了`Desc __get__ is called`信息。这是因为我们实现了`__get__()`方法,所以当我们访问`foo.d`属性时,Python会自动调用`Desc`类中的`__get__()`方法。接着,我们将`foo.d`属性设置为20,并输出了`Desc __set__ is called`信息。这是因为我们实现了`__set__()`方法,所以当我们设置`foo.d`属性时,Python会自动调用`Desc`类中的`__set__()`方法。

最后,我们手动将`foo`实例对象的`__dict__`属性中的`d`属性设置为30,并再次访问`foo.d`属性。此时,Python会优先使用`d`的数据描述符,因此输出了`Desc __get__ is called`信息。

5. 总结

本文通过多个实例来解析了Python描述符的原理和作用。我们了解了描述符的分类、在类中的应用以及在属性访问中的优先级。描述符是Python中非常强大的一个特性,可以用来实现各种行为,例如数据验证、类型转换、缓存等等,非常值得深入学习和使用。

5天短视频训练营
新手入门剪辑课程,零基础也能学
分享变现渠道,助你兼职赚钱
限时特惠:0元
立即抢
新手剪辑课程 (精心挑选,简单易学)
第一课
新手如何学剪辑视频? 开始学习
第二课
短视频剪辑培训班速成是真的吗? 开始学习
第三课
不需要付费的视频剪辑软件有哪些? 开始学习
第四课
手机剪辑app哪个好? 开始学习
第五课
如何做短视频剪辑赚钱? 开始学习
第六课
视频剪辑接单网站APP有哪些? 开始学习
第七课
哪里可以学短视频运营? 开始学习
第八课
做短视频运营需要会什么? 开始学习
相关问题
sql判断字段是否存在
python键值对
for循环可以遍历字典吗
怎么使用vscode
查看更多

客服热线:0731-85127885

湘ICP备19005950号-1  

工商营业执照信息

违法和不良信息举报

举报电话:0731-85127885 举报邮箱:tousu@csai.cn

优草派  版权所有 © 2024