Python 描述符(Descriptor)入门

Python描述符入门

什么是Python描述符?

Python描述符是一种实现了特定协议的对象,允许自定义属性访问和赋值的行为,是Python属性的核心机制之一。描述符常用于创建高级对象,例如ORM(对象关系映射)模型、表单验证和属性缓存等。在Python中,一个描述符必须实现以下方法:

  • __get__(self, instance, owner=None):访问描述符时调用的方法,返回属性的值。
  • __set__(self, instance, value):设置描述符时调用的方法,设置属性的值。
  • __delete__(self, instance):删除描述符时调用的方法。

描述符的使用方法

使用描述符,需要创建一个类,并在其中定义上述方法。当某个属性被定义为一个描述符实例时,该实例的相关方法将被调用来访问和修改属性。以下是一个实现描述符的例子:

class Descriptor:
    def __init__(self, name=None):
        self.name = name

    def __get__(self, instance, owner=None):
        if instance:
            return instance.__dict__.get(self.name)
        return self

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]

上述描述符方法中,将属性的名称保存在name参数中。__get__方法的参数instance指向拥有该属性的对象实例,owner参数指向对象的类(可选)。在返回属性值时,使用instance.__dict__.get(self.name)获取该实例中属性的值。__set__方法用来设置属性值,使用instance.__dict__[self.name] = value进行设置操作。__delete__方法用于删除属性,在这个例子中使用del instance.__dict__[self.name]来删除实例中的属性。

可以使用以上定义的描述符来定义一个类:

class Person:
    name = Descriptor('name')
    age = Descriptor('age')

使用上述类创建一个对象并尝试设置属性:

p = Person()
p.name = "Jack"
p.age = 20
print(p.name)  # 输出Jack
print(p.age)   # 输出20

描述符的应用

下面介绍两个描述符实现的例子:

描述符给属性设置只读属性

在这个例子中,我们将实现描述符来给某个属性设置只读属性。在__set__方法中,如果尝试修改值,将触发AttributeError异常。

class ReadOnlyDescriptor:
    def __init__(self, name=None):
        self.name = name

    def __get__(self, instance, owner=None):
        if instance:
            return instance.__dict__.get(self.name)
        return self

    def __set__(self, instance, value):
        raise AttributeError("Read Only Attribute")

    def __delete__(self, instance):
        del instance.__dict__[self.name]


class Person:
    name = ReadOnlyDescriptor('name')
    age = Descriptor('age')

测试代码如下:

p = Person()
p.name = "Jack"
p.age = 20
print(p.name)  # 输出Jack
# 抛出异常
try:
    p.name = "Lucy"
except AttributeError as e:
    print(e)
# 输出20
print(p.age)

描述符实现缓存属性

在这个例子中,我们将实现一个描述符来缓存一些属性,避免重复计算。在__get__方法中,如果值已经被设置过,就直接返回缓存的结果。否则计算结果并设为该属性的值,并将值保存在缓存变量cached_value中。

class CacheDescriptor:
    def __init__(self, func):
        self.func = func
        self.cached_value = None

    def __get__(self, instance, owner=None):
        if instance:
            if self.cached_value is None:
                self.cached_value = self.func(instance)
            return self.cached_value
        return self

    def __set__(self, instance, value):
        self.cached_value = value

    def __delete__(self, instance):
        self.cached_value = None


class Circle:
    def __init__(self, radius):
        self.radius = radius

    @CacheDescriptor
    def area(self):
        print("calculating area")
        return 3.14 * self.radius ** 2

测试代码如下:

c = Circle(10)
print(c.area)        # 计算面积,并输出314.0
print(c.area)        # 直接输出314.0,无需重复计算
c.radius = 5         # 修改属性后需要重新计算面积
print(c.area)        # 计算新的面积,并输出78.5

结论

以上是Python描述符的基础知识和使用方法。描述符作为Python属性的核心机制之一,可以非常灵活的定义属性的访问和修改行为,实现各种高级功能。需要注意的是,描述符是Python高级语言的一部分,初学者需要更多的实践积累经验才能熟练掌握。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 描述符(Descriptor)入门 - Python技术站

(0)
上一篇 2023年5月13日
下一篇 2023年5月13日

相关文章

  • 深度解析Python线程和进程

    深度解析Python线程和进程 Python是一门高级编程语言,它支持多线程和多进程编程。但是线程与进程是操作系统层面的概念,因此在Python中,我们使用操作系统提供的多线程/多进程API来实现多线程/多进程编程。 本文将深度解析Python中的线程和进程,介绍它们的定义、工作原理以及使用方法。 线程 定义 线程是操作系统能够进行运算调度的最小单位,它被包…

    python 2023年5月19日
    00
  • python第三方库学习笔记

    Python第三方库学习笔记 Python作为一门优秀的编程语言,拥有非常丰富的第三方库。在学习过程中,我们需要去了解、学习、使用这些第三方库,以提高编码效率和代码质量。本篇文章将简要介绍如何进行Python第三方库的学习笔记,以及如何使用第三方库。 学习步骤 学习一个新的第三方库,我们可以按照以下步骤进行: 官方文档:阅读第三方库的官方文档,了解第三方库的…

    python 2023年6月3日
    00
  • python实现图片筛选程序

    Python实现图片筛选程序的攻略如下: 1. 获取图片 使用Python中的Pillow库可以很容易地获取图片。我们可以使用以下代码来获取指定路径的图片: from PIL import Image # 打开图片 im = Image.open(‘test.jpg’) # 显示图片 im.show() 2. 图片处理 2.1 图片裁剪 我们可以使用Pill…

    python 2023年5月18日
    00
  • 详解Python中where()函数的用法

    当你想在Python中快速筛选一些数据的时候,可以使用where()函数来帮助你实现这个任务,那么,下面我们来详解Python中where()函数的用法。 什么是where()函数 where()函数是NumPy中用于数组索引的函数,它返回索引数组,该索引数组的元素指示给定条件的元素的位置。where()函数的原型如下: numpy.where(condit…

    python 2023年6月5日
    00
  • Python 3 中 execfile 的替代方案? [复制]

    【问题标题】:Alternative to execfile in Python 3? [duplicate]Python 3 中 execfile 的替代方案? [复制] 【发布时间】:2023-04-05 08:03:01 【问题描述】: Python 2 有内置函数 execfile,它在 Python 3.0 中被删除。 This question …

    Python开发 2023年4月5日
    00
  • Python下载指定页面上图片的方法

    以下是 Python 下载指定页面上图片的方法的完整攻略: 背景 在某些情况下,我们需要将网页上的图片下载到本地进行保存或处理。此时,我们可以使用 Python 来实现这一功能。 方法 Python 中有多种方式可以下载网页上的图片,常见的有以下两种方法: 方法一:使用 requests 库下载图片 import requests # 定义要下载图片的 UR…

    python 2023年6月3日
    00
  • python中requests库安装与使用详解

    Python中的requests库是一个非常常用的库,能够帮助我们更加便捷地进行HTTP请求。下面是关于该库的安装与使用的详尽攻略。 安装requests库 我们可以使用pip命令来安装requests库,命令如下: pip install requests 如果当前环境没有安装pip,我们需要先安装pip。命令如下: apt-get install pyt…

    python 2023年5月13日
    00
  • Python中xlsx文件转置操作详解(行转列和列转行)

    下面是“Python中xlsx文件转置操作详解(行转列和列转行)”的完整实例教程。 1. 背景 在日常的数据处理中,经常需要处理表格数据,而Excel中的表格数据通常都是按行存储的。但有时候我们需要将其按列进行存储,这就需要使用到转置操作。 2. 示例 在介绍具体的转置操作之前,先来看一下示例数据。 姓名 语文成绩 数学成绩 英语成绩 张三 90 95 85…

    python 2023年5月13日
    00
合作推广
合作推广
分享本页
返回顶部