Python中的魔法方法(magic methods 或 special methods)-3

news2024/9/17 8:29:45

目录

  • 通过描述符管理属性
  • 使用 Iterators 和 Iterables 支持迭代
    • Creating Iterators 创建迭代器
    • 构建可迭代对象

通过描述符管理属性

Python 描述符是允许您对给定自定义类的属性进行精细控制的类。您可以使用 Descriptors 在给定类的属性之上添加类似函数的行为。

描述符类至少需要 .__get__() 特殊方法。但是,完整描述符协议由以下方法组成:

方法描述
__get__(self, instance, type=None)Getter 方法,该方法允许您检索 managed 属性的当前值
__set__(self, instance, value)允许您为 managed 属性设置新值的 Setter 方法
__delete__(self, instance)Deleter 方法,该方法允许您从包含类中删除 managed 属性
__set_name__(self, owner, name)名称 setter 方法,用于定义托管属性的名称

为了说明 Descriptors 的用途,假设您有一个 shapes.py 模块。您已经定义了 Circle、Square 和 Rectangle 类。您已经意识到需要验证圆的半径、正方形的边等参数。您还注意到,验证逻辑对于所有这些参数都是通用的。

在这种情况下,您可以使用描述符来管理验证逻辑,其中包括检查提供的值是否为正数。以下是此 Descriptors 的可能实现:

class PositiveNumber:
    def __set_name__(self, owner, name):
        self._name = name

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

    def __set__(self, instance, value):
        if not isinstance(value, int | float) or value <= 0:
            raise ValueError("positive number expected")
        instance.__dict__[self._name] = value

在此类中,首先定义 .__set_name__() 特殊方法。owner 参数表示包含类,而 name 参数表示属性名称。

然后,定义 .__get__() 方法。此方法采用一个实例和对包含类的引用。在此方法中,使用 .dict 特殊属性来访问实例的命名空间并检索 managed 属性的值。

最后,定义 .__set__() 方法,该方法采用包含类的实例和 managed 属性的新值。在此方法中,您将检查提供的值是否为正数,在这种情况下,您将引发 ValueError 异常。否则,您将再次使用 .__dict__ 命名空间将 input 值分配给 managed 属性。

现在,您可以使用此描述符来定义形状的参数:

import math

# ...

class Circle:
    radius = PositiveNumber()

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

    def area(self):
        return round(math.pi * self.radius**2, 2)

class Square:
    side = PositiveNumber()

    def __init__(self, side):
        self.side = side

    def area(self):
        return round(self.side**2, 2)

class Rectangle:
    height = PositiveNumber()
    width = PositiveNumber()

    def __init__(self, height, width):
        self.height = height
        self.width = width

    def area(self):
        return self.height * self.width

在此代码中,突出显示的行显示了如何使用 PositiveNumber 描述符创建托管属性。请注意,托管属性必须是具有实例属性对应项的类属性。

以下是Shape使用方式:

>>> from shapes import Circle, Square, Rectangle

>>> circle = Circle(-10)
Traceback (most recent call last):
    ...
ValueError: positive number expected

>>> square = Square(-20)
Traceback (most recent call last):
    ...
ValueError: positive number expected

>>> rectangle = Rectangle(-20, 30)
Traceback (most recent call last):
    ...
ValueError: positive number expected

所有形状都会在实例化时验证输入参数。这是因为他们都使用你的 PositiveNumber 来管理他们的参数。这样,你就可以在所有类中重复使用验证代码。

使用 Iterators 和 Iterables 支持迭代

在 Python 中,迭代器和可迭代对象是两种不同但相关的工具,当您需要迭代数据流或容器时,它们可以派上用场。Iterators 支持并控制迭代过程,而 iterables 通常保存您可以迭代的数据。

迭代器和可迭代对象是 Python 编程中的基本组件。您将在几乎所有程序中直接或间接使用它们。在以下部分中,您将学习如何使用特殊方法将自定义类转换为迭代器和可迭代对象的基础知识。

Creating Iterators 创建迭代器

要在 Python 中创建迭代器,您需要两个特殊方法。通过实现这些方法,您将控制迭代过程。您可以定义在 for 循环或其他迭代构造中使用类时 Python 如何检索项。
下表显示了组成迭代器的方法。它们被称为迭代器协议:

方法描述
__iter__() 调用以初始化迭代器。它必须返回一个 iterator 对象。
__next__()调用以迭代迭代器。它必须返回数据流中的下一个值。

这两种方法都有自己的责任。在 .__iter__() 中,您通常返回当前对象 self。在 .__next__() 中,您需要返回序列中数据流中的下一个值。当数据流耗尽时,此方法必须引发 StopIteration。这样,Python 就知道迭代已经结束。
通过在自定义类中实现这两个方法,可以将它们转换为迭代器。例如,假设您要创建一个类,该类为斐波那契数列中的数字提供迭代器。在这种情况下,您可以编写以下解决方案:

class FibonacciIterator:
    def __init__(self, stop=10):
        self._stop = stop
        self._index = 0
        self._current = 0
        self._next = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self._index < self._stop:
            self._index += 1
            fib_number = self._current
            self._current, self._next = (
                self._next,
                self._current + self._next,
            )
            return fib_number
        else:
            raise StopIteration

在这个 FibonacciIterator 类中,您首先初始化一些 attributes。._stop 属性定义类将返回的值的数量。默认为 10。._index 属性保存序列中当前斐波那契值的索引。._current 和 ._next 属性分别表示斐波那契数列中的当前值和下一个值。

.__iter__() 中,你只需返回当前对象 self。在 Python 中创建迭代器时,这种做法很常见。

.__next__() 方法要复杂一些。在此方法中,您有一个条件,用于检查当前序列索引是否未达到 ._stop 值,在这种情况下,您可以递增当前索引以控制迭代过程。然后,您计算与当前索引对应的斐波那契数,并将结果返回给 .__next__() 的调用方。

当 ._index 增长到 ._stop 的值时,将引发 StopIteration 异常,这将终止迭代过程。

您的类现在已准备好进行迭代。以下是它的使用:

>>> from fib_iter import FibonacciIterator

>>> for fib_number in FibonacciIterator():
...     print(fib_number)
...
0
1
1
2
3
5
8
13
21
34

FibonacciIterator 类实时计算新值,当您在循环中使用该类时,会按需生成值。当斐波那契值的数量增长到 10 时,该类将引发 StopIteration 异常,并且 Python 会终止循环。

构建可迭代对象

Iterables 与 iterators 略有不同。通常,当集合或容器实现 .__iter__() 特殊方法时,它是可迭代的。

例如,Python 内置容器类型(如列表、元组、字典和集)是可迭代对象。它们提供您可以迭代的数据流。但是,它们不提供 .__next__() 方法,该方法驱动迭代过程。因此,要使用 for 循环迭代可迭代对象,Python 会隐式创建一个迭代器。

例如,返回到 Stack 类。使用以下代码更新类以使其可迭代:

class Stack:
    # ...

    def __iter__(self):
        return iter(self.items[::-1])

请注意,.__iter__() 的这个实现不会返回当前对象 self。相反,该方法使用内置的 iter() 函数在堆栈中的项目上返回一个迭代器。iter() 函数为输入可迭代对象提供默认的 .__next__() 方法,使其成为一个成熟的迭代器。

在迭代之前反转堆栈中的项列表,以与元素从堆栈中弹出的顺序保持一致。在 Python 交互式会话中运行以下代码以试用 Stack 的这项新功能:

>>> from stack import Stack

>>> stack = Stack([1, 2, 3, 4])

>>> for value in stack:
...     print(value)
...
4
3
2
1

在此代码段中,您首先创建一个包含四个数字的 Stack 新实例。然后,在实例上启动 for 循环。循环在每次迭代中打印当前值。这表明如果你重复调用 .pop() ,顺序元素将被弹出。您的 Stack 类现在支持迭代。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring揭秘19-spring事务01-事务抽象

文章目录 【README】【1】事务基本元素【1.1】事务分类 【2】java事务管理【2.1】基于java的局部事务管理【2.2】基于java的分布式事务管理【2.2.1】基于JTA的分布式事务管理【2.2.2】基于JCA的分布式事务管理 【2.3】java事务管理的问题 【3】spring事务抽象概述【3.1】spring…

easyExcel-读取Excel

1、简单读取&#xff0c;没有合并单元格 2、复杂读取&#xff0c;合并单元格-方法一 1、简单读取&#xff0c;没有合并单元格 1.1、引入pom文件 <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.…

【单片机】详细解析完全重映射和部分重映射

1、重映射的作用 单片机中的每个引脚通常都有多个功能&#xff0c;不仅仅是作为普通的输入或输出&#xff0c;还可以与某些外设&#xff08;如定时器、串口、SPI、I2C等&#xff09;关联。默认情况下&#xff0c;这些外设功能通常固定绑定到特定的GPIO引脚。但是&#xff0c;在…

Matplotlib颜色透明度设置

matplotlib中的透明度设置都是通过alpha设置的,一般在能设置颜色的包括背景色、图表色、文字颜色都可以设置透明度 float类型,取值范围为[0.0,1.0],alpha取值越小越透明 import numpy as np import matplotlib.pyplot as pltx np.linspace(0, 2*np.pi, 100) y np.sin(x) y1…

Arch - 架构安全性_授权(Authorization)

文章目录 OverView授权&#xff08;Authorization&#xff09;RBAC&#xff1a; 概述RBAC&#xff1a;基于角色的访问控制RBAC&#xff1a;主要元素 OAuth2&#xff1a;面向第三方应用的认证授权协议业务场景OAuth2的工作流程OAuth2 四种不同的授权方式授权码模式&#xff08;A…

Android Studio 2024最新版Hello World

Android Studio 2024最新版Hello World 1. Android Studio 2024安装视频2. 创建项目Read Timed out 问题Android Studio Build Output 控制台中文乱码问题 3. 驱动管理 本文章介绍如何通过Android Studio 2024最新版创建项目&#xff0c; 并成功输出Hello World。 本次教程版本…

关于QT中使用网络编程QtNetwork的问题

在此处添加network模块 在链接器中添加附加库目录(QT对应的lib)在链接器-输入中添加对应的lib库(Qt5Network.lib) 这样,就可以使用对应的下面的库文件了,比如: #include <qnetworkaccessmanager.h>

参数高效微调(PEFT)综述

人工智能咨询培训老师叶梓 转载标明出处 大模型如BERT和GPT-3的参数数量庞大&#xff0c;动辄数十亿甚至数千亿级别&#xff0c;给进一步的微调和应用带来了巨大的挑战。针对这一问题&#xff0c;Vladislav Lialin、Vijeta Deshpande、Anna Rumshisky等研究者中提出了一系列参…

Leetcode面试经典150题-69.X的平方根

相当简单的题目&#xff0c;但是出现的概率还挺高的 解法都在代码里&#xff0c;不懂就留言或者私信 class Solution {public int mySqrt(int x) {/**0的平方根是0 */if(x 0) {return 0;}/**1~3的平方根是1 */if(x < 3) {return 1;}/**其他情况我们采用二分查找&#xff…

Python 调用手机摄像头

Python 调用手机摄像头 在手机上安装软件 这里以安卓手机作为演示&#xff0c;ISO也是差不多的 软件下载地址 注意&#xff1a;要想在电脑上查看手机摄像头拍摄的内容的在一个局域网里面(没有 WIFI 可以使用 热点 ) 安装完打开IP摄像头服务器 点击分享查看IP 查看局域网的I…

Android Studio下载Gradle失败问题解决

问题说明 使用 Android Studio 构建程序报错如下 Could not install Gradle distribution from https://services.gradle.org/distributions/gradle-7.5.1-bin.zip. Reason: java.net.SocketTimeoutException: Connect timed out问题解决 下载对应版本的压缩包 gradle-7.5.1…

香橙派转换模型以及在开发板上部署

新手小白记录一下自己使用香橙派模型转换以及在开发板上运行的过程&#xff0c;防止后面忘记。 使用的开发板&#xff1a;Orange Pi 5 Plus&#xff08;rk3588&#xff09; 官方的一些资料在&#xff08;主要参考用户手册&#xff09;&#xff1a;Orange Pi - Orangepihttp:/…

价格适中超微小间距P1.8全彩LED显示屏广泛应用于COB会议一体机

随着科技的不断进步与市场需求的日益多样化&#xff0c;价格适中且具备超微小间距P1.8技术的全彩LED显示屏&#xff0c;在COB&#xff08;Chip On Board&#xff09;会议一体机领域的应用正逐步深化&#xff0c;引领着现代会议展示的新风尚。这种显示屏不仅以其细腻的画质和卓越…

单片机DMA原理及应用详解(下篇)(附工程源码)

这篇文章详细介绍单片机的DMA原理和应用范例。希望我的分享能给你带来不一样的收获&#xff01; 关于DMA的原理&#xff0c;可以看上一篇文章&#xff1a; 单片机DMA原理及应用详解&#xff08;上篇&#xff09;&#xff08;附工程源码&#xff09;-CSDN博客 目录 一、STM32单片…

黑龙江IBM Storwize v3700存储故障维修

中国黑龙江省佳木斯IBM Storwize v3700存储控制器故障维修案例&#xff1a; 报修单位&#xff1a;黑龙江佳木斯某某医院 存储型号&#xff1a;联想或IBM v3700 存储故障&#xff1a;无法正常访问存储磁盘&#xff0c;无法进存储web管理界面&#xff0c;可以进存储服务助手界…

《C++ 中的左值与右值》

在 C 的世界里&#xff0c;左值和右值是两个重要的概念&#xff0c;理解它们对于掌握 C 语言的精髓至关重要。 首先&#xff0c;我们来认识左值。左值&#xff0c;即 “locator value”&#xff0c;可以理解为有明确存储位置且可以被取地址的表达式。简单来说&#xff0c;一个可…

Linux之MySQL主从复制

概述 MySQL的主从复制&#xff08;Master-Slave Replication&#xff09;是一种数据复制解决方案&#xff0c;将主数据库的DDL&#xff08;数据定义语言&#xff09;和DML&#xff08;数据操纵语言&#xff09;操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这…

自动驾驶ADAS算法--使用MATLBA和UE4生成测试视频

原文参考&#xff1a;金书世界 环境搭建参考&#xff1a;用MATLAB2020b和虚拟引擎&#xff08;Unreal Engine&#xff09;联合仿真输出AVM全景测试视频----Matlab环境搭建 matlab参考&#xff1a; https://ww2.mathworks.cn/help/driving/ug/simulate-a-simple-driving-sce…

Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

文章目录 一、Home模块拆分1. 三级联动组件TypeNav2. 其余组件 二、发送请求的准备工作1. axios的二次封装2. 统一管理接口API----跨域3. nprogress进度条 三、 vuex模块开发四、TypeNav三级联动组件开发1. 动态展示三级联动数据2. 三级联动 动态背景(1)、方式一&#xff1a;CS…

CAS概念、性质、优缺点 | 乐观锁、悲观锁是什么?

前言&#xff1a; 今天在深入了解HashMap时&#xff0c;看到这句话&#xff1a;“concurrentHashMap&#xff0c;在 JDK 1.7 中采用 分段锁的方式&#xff1b;JDK 1.8 中直接采用了CAS&#xff08;无锁算法&#xff09; synchronized。” 哦~~这个CAS好像之前接触过&#xff0c…