一文搞懂Python对象的描述器机制

 更新时间:2025年05月29日 08:30:46   作者:烛阴  
在Python中,“描述器”是一种能够自定义对象属性访问(获取、设置、删除)行为的协议,它是实现@property、类属性、ORM字段、类型检查的底层支撑,本文将带你玩转Python对象的描述器机制,需要的朋友可以参考下

一、什么是Python描述器?

在Python中,“描述器”是一种能够自定义对象属性访问(获取、设置、删除)行为的协议。它是实现@property、类属性、ORM字段、类型检查的底层支撑。

一句话解释:只要一个对象定义了__get____set____delete__等特殊方法,并作为另一个类的类属性,这个对象就成了描述器!

默认对属性的访问控制是从对象的字典里面 (__dict__) 中获取 (get) , 设置 (set) 和删除 (delete) 。

举例来说, a.x 的查找顺序是, a.__dict__['x'] , 然后 type(a).__dict__['x'] , 然后找 type(a) 的父类 ( 不包括元类 (metaclass) ).如果查找到的值是一个描述器, Python 就会调用描述器的方法来重写默认的控制行为。

二、描述器协议:三大魔法方法

方法作用用法场景
__get__获取属性时调用动态计算、懒加载
__set__设置属性时调用数据验证、只读限制
__delete__删除属性时调用管控属性生命周期

最简单的描述器雏形:

class DemoDescriptor:
    def __get__(self, instance, owner):
        print('执行了__get__')
        return 42

class MyClass:
    x = DemoDescriptor()

obj = MyClass()
print(obj.x)  # 输出42,中间会打印“执行了__get__”

三、入门实战:搞懂描述器工作的方式

3.1 数据描述器 VS 非数据描述器

  • 数据描述器 : 同时定义了__get____set__
  • 非数据描述器 : 只定义了__get__

数据描述器拥有更高优先级,会屏蔽实例字典上的同名属性!

3.2 数据描述器基础案例

class Typed:
    def __init__(self, name, typ):
        self.name = name
        self.typ = typ

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, self.typ):
            raise TypeError(f'属性{self.name}必须是{self.typ}')
        instance.__dict__[self.name] = value

class Person:
    age = Typed('age', int)    # 用描述器控制
    name = Typed('name', str)

p = Person()
p.age = 18            # 自动类型检查
p.name = '小明'
# p.age = 'not int'   # 抛出TypeError

四、@property 与描述器的关系

你用过的@property,其实就是“非数据描述器”的语法糖:

class Demo:
    @property
    def val(self):
        return 666

底层实现和你定义带__get__的对象如出一辙。

五、进阶:自定义描述器封装与通用实现

5.1 描述器工厂 基于装饰器快速生成校验字段

def typed_field(name, typ):
    class _TypedDescriptor:
        def __get__(self, instance, owner):
            return instance.__dict__[name]
        def __set__(self, instance, value):
            if not isinstance(value, typ):
                raise TypeError(f"属性{name}必须是{typ}")
            instance.__dict__[name] = value
    return _TypedDescriptor()

class Student:
    age = typed_field('age', int)
    name = typed_field('name', str)

stu = Student()
stu.age = 18    # √
# stu.age = 'oops' # TypeError

5.2 只读属性描述器

class ReadOnly:
    def __init__(self, value):
        self._value = value
    def __get__(self, instance, owner):
        return self._value

class System:
    version = ReadOnly('1.0.0')

print(System.version)   # '1.0.0'

到此这篇关于一文搞懂Python对象的描述器机制的文章就介绍到这了,更多相关Python对象描述器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python求解任意闭区间的所有素数

    Python求解任意闭区间的所有素数

    本篇文章是一篇关于python求素数的知识点内容,如果大家在应用中有用的到,不妨跟着学习下。
    2018-06-06
  • 如何在Python3中使用telnetlib模块连接网络设备

    如何在Python3中使用telnetlib模块连接网络设备

    这篇文章主要介绍了如何在Python3中使用telnetlib模块连接网络设备,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 使用Python处理Excel表格的简单方法

    使用Python处理Excel表格的简单方法

    这篇文章主要介绍了使用Python处理Excel表格的简单方法,本文给大家介绍的非常详细,需要的朋友可以参考下
    2018-06-06
  • python基础教程之自定义函数介绍

    python基础教程之自定义函数介绍

    这篇文章主要介绍了python基础教程之自定义函数介绍,本文讲解了python中函数的定义方法、函数参数的定义方法,需要的朋友可以参考下
    2014-08-08
  • Pycharm及python安装详细步骤及PyCharm配置整理(推荐)

    Pycharm及python安装详细步骤及PyCharm配置整理(推荐)

    这篇文章主要介绍了Pycharm及python安装详细步骤以及PyCharm配置整理,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Python操作Excel神器openpyxl使用教程(超详细!)

    Python操作Excel神器openpyxl使用教程(超详细!)

    openpyxl库是一个很好处理xlsx的python库,下面这篇文章主要给大家介绍了关于Python办公自动化openpyxl使用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • python 引用传递和值传递详解(实参,形参)

    python 引用传递和值传递详解(实参,形参)

    这篇文章主要介绍了python 引用传递和值传递详解(实参,形参)。具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06
  • Python中的yield浅析

    Python中的yield浅析

    这篇文章主要介绍了Python中的yield浅析,对迭代器(iterator) 、生成器(constructor)一并做了分析,并用实例来说明,需要的朋友可以参考下
    2014-06-06
  • 解决python文件字符串转列表时遇到空行的问题

    解决python文件字符串转列表时遇到空行的问题

    下面小编就为大家带来一篇解决python文件字符串转列表时遇到空行的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Python+Yolov5人脸口罩识别的详细步骤

    Python+Yolov5人脸口罩识别的详细步骤

    人脸口罩佩戴检测(识别)是当前急需的应用,而YOLOv5是目前流行的强悍的目标检测技术,下面这篇文章主要给大家介绍了关于Python+Yolov5人脸口罩识别的相关资料,需要的朋友可以参考下
    2022-12-12

最新评论