Python教程(23)——Python类中常用的特殊成员

news2024/9/22 9:44:13

在Python中,类特殊成员是指以双下划线开头和结尾的属性和方法,也被称为魔术方法(Magic methods)或特殊方法(Special methods)。这些特殊成员在类的定义中具有特殊的语法和功能,用于实现对象的特定行为和操作。

特殊方法一般由Python解释器调用,无需手动调用。通过在类中定义这些特殊方法,可以改变对象的默认行为,使其具备更多的功能和操作。特殊方法提供了一种更加Pythonic的面向对象编程的方式,可以让代码更加简洁和易读。
在这里插入图片描述

__init__

__init__ 是Python中的一个特殊方法,也被称为构造方法。它在创建对象时自动调用,用于初始化对象的属性。通过在类中定义 __init__ 方法,我们可以在对象创建时为其赋予初始状态,设置属性的默认值,或执行其他必要的初始化操作。

__init__ 方法的格式通常如下:

def __init__(self, arg1, arg2, ...):
    self.attribute1 = arg1
    self.attribute2 = arg2
    # ...

self 代表对象本身,arg1arg2 等是用于接收传入的参数的形参,我们可以根据实际需要为 __init__ 方法传入不同的参数。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person1 = Person("Alittle", 30)

__init__ 方法中,我们可以执行其他的初始化操作,例如连接数据库、打开文件、设置默认值等。这使得我们能够在创建对象时,做一些必要的准备工作,确保对象在初始化后即可用。

需要注意的是,Python 中的 __init__ 方法是可选的,不是必须定义的。如果类中没有定义 __init__ 方法,Python 会使用默认的空的 __init__ 方法。但通常情况下,我们会定义 __init__ 方法来初始化对象的属性。

__del__

__del__ 是Python中的一个特殊方法,也被称为析构方法。它在对象被销毁前自动调用,用于进行清理工作。当对象的引用计数为零时(即没有任何变量引用该对象),Python解释器会自动触发 __del__ 方法的调用。

__del__ 方法的格式通常如下:

def __del__(self):
    # 清理代码

__del__ 方法中,self 代表对象本身。我们可以在 __del__ 方法中编写需要在对象销毁之前执行的清理代码,例如关闭文件、释放资源、记录日志等。

class FileHandler:
    def __init__(self, filename):
        self.file = open(filename, 'w')

    def write_data(self, data):
        self.file.write(data)

    def __del__(self):
        self.file.close()

handler = FileHandler("data.txt")
handler.write_data("Hello, World!")
# 在退出程序或手动执行 del handler 时,会自动调用 __del__ 方法关闭文件

我们定义了一个 FileHandler 类,其中的 __init__ 方法用于打开文件并创建一个 file 对象。write_data 方法用于向文件写入数据。在 __del__ 方法中,我们通过 self.file.close() 关闭了文件。当程序退出或手动执行 del handler 时,对象 handler 被销毁,会自动调用 __del__ 方法关闭文件,确保资源的正常释放。

另外需要注意的是,__del__ 方法的调用是由Python解释器自动控制的,并不是我们手动调用的。因此,我们不能依赖 __del__ 方法来进行关键性的清理工作,如释放内存。一般来说,Python有自己的垃圾回收机制,会自动管理对象的内存释放。我们只需确保在 __del__ 方法中执行一些简单的清理操作即可。此外,应尽量避免在 __del__ 方法中抛出异常,以免影响其他代码的执行。

__str__

__str__ 也是Python中的一个特殊方法,也被称为字符串表示方法。它定义了当我们对一个对象使用内置的 str() 函数或 print() 函数进行输出时,应该返回的字符串形式表示。简而言之,__str__ 方法用于定制对象的字符串输出。

__str__ 方法的格式通常如下:

def __str__(self):
    # 返回表示对象的字符串

__str__ 方法中,self 代表对象本身,没有其他的参数了,我们可以在该方法中编写需要返回的表示对象的字符串形式的代码,例如组织对象的属性信息、状态等。

以下是一个示例,展示了如何使用 __str__ 方法来定制对象的字符串输出:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        print("call __str__")
        return f"Point({self.x}, {self.y})"

p = Point(3, 4)
print(p)
print("-----------------")
str(p)

上面的示例中的输出

call __str__
Point(3, 4)
-----------------
call __str__

我们定义了一个 Point 类,其中的 __init__ 方法用于初始化点的坐标。在 __str__ 方法中,我们使用格式化字符串 f-string 将点的坐标表示为 ‘(x, y)’ 的形式。当我们对 p 对象使用 print(p)str(p) 时,会自动调用 __str__ 方法,并返回该方法中定义的字符串 (3, 4)

__repr__

__repr____str__ 方法类似,下面直接用一个例子来说明这个和 __str__ 的区别。

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        print("call __str__")
        return f"Point1({self.x}, {self.y})"

    def __repr__(self):
        print("call __repr__")
        return f"Point2({self.x}, {self.y})"

p = Point(3, 4)
print(p)
print("-----------------")
str(p)
repr(p)

上面的示例中的输出

call __str__
Point1(3, 4)
-----------------
call __str__
call __repr__

从上面的输出可以看出,repr(p) 函数可以自动调用 __repr__,默认情况下,__str____repr__ 同时存在的话,str()print()函数就会优先调用 __str__,而如果只有 __repr__ 的话,就会调用 __repr__,不信你们可以把上面例子中的 __str__ 注释掉,然后看看输出情况。

__len__

__len__ 用于定义对象的长度。它主要被用于内置函数 len() 的操作,用于返回一个对象的长度或元素的个数。

__len__ 方法的格式通常如下:

def __len__(self):
    # 返回对象的长度或元素的个数

__len__ 方法中,self 代表对象本身。我们可以在该方法中编写代码,返回一个整数,表示对象的长度或元素的个数。

以下是一个示例,展示了如何使用 __len__ 方法来定义一个自定义的容器类并使用 len() 函数获取其长度:

class MyContainer:
    def __init__(self):
        self.data = []

    def __len__(self):
        return len(self.data)

    def add(self, element):
        self.data.append(element)

container = MyContainer()
container.add(1)
container.add(2)
container.add(3)

print(len(container))  # 输出 3,调用了 __len__ 方法

在上面的示例中,我们定义了一个名为 MyContainer 的容器类,该类包含一个名为 data 的列表用于存储元素。在 __len__ 方法中,我们使用内置函数 len() 计算了 data 列表的长度,并返回该长度。当我们通过调用 len(container) 来获取 container 对象的长度时,实际上会自动调用 __len__ 方法,并返回该方法中定义的长度值。

__len__ 方法应该返回一个整数,表示对象的长度或元素的个数。如果一个类没有定义 __len__ 方法,或者 __len__ 方法返回的值不是整数类型,那么调用 len() 函数时会抛出 TypeError 异常。

__getitem__和__setitem__

__getitem____setitem__ 几乎都是成对出现的,__getitem__ 用于定义对象的索引操作,即允许通过索引值访问对象的元素,__setitem__ 用于定义对象的赋值操作,即允许通过索引值设置对象的元素值,它主要用于支持下标操作和切片操作。

__getitem____setitem__ 方法的格式通常如下:

def __getitem__(self, index):
    # 返回指定索引位置的元素

def __setitem__(self, index, value):
    # 设置指定索引位置的元素为指定的值

这两个方法一个就是取值,一个就是赋值,主要就是应用在对象上面,相对而言比较好理解。

class MyList:
    def __init__(self):
        self.data = []

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

mylist = MyList()
mylist.data = [1, 2, 3, 4, 5]

print(mylist[2])  # 输出 3,调用了 __getitem__ 方法
mylist[2] = 10  # 调用了 __setitem__ 方法赋值
print(mylist[2])  # 输出 10,调用了 __getitem__ 方法

在上面的示例中,我们定义了一个名为 MyList 的列表类,该类包含一个名为 data 的列表用于存储元素。通过实现 __getitem____setitem__方法,我们可以使用类似于列表的方式通过索引来访问和设置 data 列表中的元素。
__getitem__ 方法通常与 __setitem__ 方法一起使用,以支持对象的索引和切片操作。通过定义这些方法,我们可以使自定义的类对象能够像内置的容器类型一样进行元素的访问和修改。

如果一个类没有定义 __getitem____setitem__方法,或者__getitem____setitem__方法不能处理给定的索引值或切片对象,那么当我们尝试通过索引或切片来访问(设置)对象时,会抛出 TypeError 异常。

__call__

__call__ 用于使对象能够像函数一样被调用。通过定义 __call__ 方法,我们可以将一个对象变成一个可调用的实例,类似于函数的行为。

__call__ 方法的格式通常如下:

def __call__(self, *args, **kwargs):
    # 定义对象的调用逻辑

__call__ 方法中,self 代表对象本身,argskwargs 是传递给对象调用时的参数。

当我们像调函数一样使用对象时,Python 解释会自动调用对象的 __call__ 方法,并将传入的参数作为参数递给该方法。我们可以在 __call__ 方法中定义对象的调用逻,然后执行相应的操作。

以下一个示例,展示了如何使用 __call__ 方法来定义一个可调用的对象:

class Adder:
    def __call__(self, x, y):
        return x + y

add = Adder()

# 将对象 add 当作函数进行调用
result = add(3, 5)
print(result)  # 输出:8

在上述示例中,我们定义了一个 Adder 类,并实现了 __call__ 方法。在该方法中,我们将传入的两个参数进行相加,Python 解释器会自动调用对象 add__call__ 方法,并将传递给该方法。__call__ 方法中的逻辑会被执行,参数进行相加操作,然后返回结果。

通过使用 __call__ 方法,我们可以将一个对象实例化后,即可像函数一样进行调用,并执行预定义的逻辑。这样可以增加对象的灵活性,使其更加接近函数的行为。__call__ 方法只有在对象被调用时才会被调用,也就是对象被函数那样调用。

通常情况下,__call__ 方法常用于实现可调用的对象,如自定义的函数对象、装饰器、上下文管理器等。通过定义 __call__ 方法,我们可以使对象具有函数的特性,并能够直接调用执行相应的逻辑。

更多精彩内容,请关注同名公众:一点sir(alittle-sir)

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

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

相关文章

【python入门】day26: 模拟高铁售票系统

界面 代码 #-*- coding:utf-8 -*- import prettytable as pt#---------导入漂亮表格 import os.path filename ticket.txt#更新座位状态 def update(row_num):#------更新购票状态with open(filename,w,encodingutf-8) as wfile:for i in range(row_num):lst1 [f{i1},有票,有…

学习回顾总结

简述 哈喽大家好,记得上一次发文是在2020年的8月,当时是在西工大的长安校区做实验,在那里写了上一篇博客基于STM32f103ZET6单片机按键控制电机正反转(带PWM调速)。时间过得飞快,现在是2024年的1月&#xff…

【STM32】HAL库的RCC复位状态判断及NVIC系统软件复位

【STM32】HAL库的RCC复位状态判断及NVIC系统软件复位 在实际开发中 有时候会遇到复位状态不同 导致结果不同的情况 比如在上电复位时 电压不稳定 可能导致一些外部芯片无法正常工作 从而导致进行了错误的操作流程 所以 可以在程序运行后 加一个复位状态判断 用来检测是否正常复…

【代码随想录04】24. 两两交换链表中的节点 19. 删除链表的倒数第 N 个结点 面试题 02.07. 链表相交 142. 环形链表 II

24. 两两交换链表中的节点 题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 做题思路 可以设置虚拟头结点cur和画图…

Java 使用 JDBC 连接mysql

之前我们学习了JavaSE,编写了Java程序,数据保存在变量、数组、集合等中,无法持久化,后来学习了IO流可以将数据写入文件,但不方便管理数据以及维护数据的关系; 后来我们学习了数据库管理软件MySQL&#xff…

POI-tl 知识整理:整理1 -> 利用模板向word中写入数据

1 文本传值 Testpublic void testText() throws Exception {XWPFTemplate template XWPFTemplate.compile("D:\\Idea-projects\\POI_word\\templates.docx");Map<String, Object> map new HashMap<>();map.put("title", "Hi, girl"…

针对大规模服务日志敏感信息的长效治理实践

文章目录 1 背景2 目标与措施3 实施3.1 脱敏工具类3.2 JSON脱敏3.3 APT自动脱敏3.3.1 本地缓存问题3.3.2 JDK序列化问题 3.4 弃用方案 4 规划5 总结 1 背景 近年来&#xff0c;国家采取了多项重要举措来加强个人数据保护&#xff0c;包括实施《中华人民共和国网络安全法》和《…

JAVA毕业设计632—基于Java+ssm的宠物店商城系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于Javassm的宠物店商城系统(源代码数据库)632 一、系统介绍 本项目分为用户、营养师、管理员三种角色 1、用户&#xff1a; 登录、注册、宠物信息、宠物粮食、宠物用品、宠物疫…

imx6ull基于yocto工程的l汇编点亮ed

通过汇编点亮led 在裸机状态下通过汇编点亮led&#xff0c;即没有操作系统&#xff0c;(uboot kernel rootfs 都不需要实现&#xff09;。 led点亮原理 1.GPIO复用 根据原理图&#xff0c;找到led对应的引脚&#xff08;pin)&#xff0c;复用为GPIO&#xff08;只有GPIO才能…

平衡搜索二叉树(AVL树)

目录 前言 一、AVL树的概念 二、AVL树的定义 三、AVL树的插入 四、AVL树的旋转 4.1、右单旋 4.2、左单旋 4.3、左右双旋 4.4、右左双旋 五、AVL树的验证 5.1、 验证其为二叉搜索树 5.2、 验证其为平衡树 六、AVL树的性能 前言 二叉搜索树虽可以缩短查找的效率&…

对快速排序思想的进一步理解,分而治之,欧几里得算法(常用求最大公约数的方法)

自己找到的最优的快排的代码 快速排序 思想 分而治之使用欧几里得算法&#xff08;辗转相除法&#xff09;来求解一个应用题 假设有一块地&#xff0c;现在用这个同样大小的正方形来铺满&#xff0c;求所可用的最大的正方形地砖的面积 这两个方法放在一起是因为这个欧几里得要…

JS中的File(二):TypedArray和ArrayBuffer详解

目录 一、TypedArray 1、定义 2、注意事项 二、ArrayBuffer 1、定义和构造 2、属性 3、方法 4、使用意义 三、Blob、TypedArray和ArrayBuffer的互相转换 1、websocket接收arrayBuffer 2、blob转arrayBuffer 3、arrayBuffer to Blob 4、ArrayBuffer to Uint8数组&am…

两周掌握Vue3(五):自定义指令、路由、ajax

文章目录 一、自定义指令1.创建和使用自定义指令2.钩子函数3.使用参数 二、路由1.创建一个router实例2.在components目录中创建组件3.将路由实例挂载到应用4.使用路由 三、Ajax 代码仓库&#xff1a;跳转 当前分支&#xff1a;05 一、自定义指令 自定义指令是Vue.js框架提供的…

掌握WPF控件:熟练常用属性(一)

WPF布局常用控件&#xff08;一&#xff09; Border Border控件是一个装饰控件&#xff0c;用于围绕其他元素绘制边框和背景。它提供了一种简单的方式来为其他控件添加边框和背景样式&#xff0c;而无需自定义控件的绘制逻辑。 常用属性描述Background用于设置背景颜色或图像…

增删改查管理系统 总结1

//提醒&#xff1a; 管理员也要有增删改查 新增员工代码完善2可能需要用到 目录 细节1 pom文件出现奇怪页面&#xff1f; 细节2 如何联系DataGrip与idea&#xff1f; 细节3 Yapi?接口文档&#xff1f;如何有以下画面&#xff1f; ​细节4 如何将时间转化为好看的时间&…

【.NET Core】Lazy<T> 实现延迟加载详解

【.NET Core】Lazy 实现延迟加载详解 文章目录 【.NET Core】Lazy<T> 实现延迟加载详解一、概述二、Lazy<T>是什么三、Lazy基本用法3.1 构造时使用默认的初始化方式3.2 构造时使用指定的委托初始化 四、Lazy.Value使用五、Lazy扩展用法5.1 实现延迟属性5.2 Lazy实现…

语义分割miou指标计算详解

文章目录 1. 语义分割的评价指标2. 混淆矩阵计算2.1 np.bincount的使用2.2 混淆矩阵计算 3. 语义分割指标计算3.1 IOU计算方式1(推荐)方式2 3.2 Precision 计算3.3 总体的Accuracy计算3.4 Recall 计算3.5 MIOU计算 参考 MIoU全称为Mean Intersection over Union&#xff0c;平均…

山西电力市场日前价格预测【2024-01-13】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-13&#xff09;山西电力市场全天平均日前电价为231.81元/MWh。其中&#xff0c;最高日前电价为345.71元/MWh&#xff0c;预计出现在00:15。最低日前电价为0.00元/MWh&#xff0c;预计出…

大模型实战笔记04——XTuner 大模型单卡低成本微调实战

大模型实战笔记04——XTuner 大模型单卡低成本微调实战 1、Finetune简介 2、XTuner 3、8GB显存玩转LLM 4、动手实战环节 注&#xff1a; 笔记内容均为截图 课程视频地址&#xff1a;https://www.bilibili.com/video/BV1yK4y1B75J/?spm_id_from333.788&vd_source2882acf…

行为型设计模式——备忘录模式

备忘录模式 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以方便地回到一个特定的历史步骤&#xff0c;当新的状态无效或者存在问题时&#xff0c;可以使用暂时存储起来的备忘录将状态复原&#xff0c;很多软件都提供了撤销&#xff08;Undo&#xff09;操作…