Python中的魔法函数

        大家好,Python作为一种高级编程语言,以其简洁、优雅和易读性而闻名。然而,Python的强大之处不仅仅在于其语法的简洁性,还在于其灵活的面向对象编程范式。在Python中,有一类特殊的方法被称为“魔法函数”,它们以双下划线(__)开头和结尾,为Python提供了一种强大的机制,使得用户能够定制类的行为,使其更加符合特定的需求和使用场景。

一、介绍

1、什么是Python魔法函数?

        在Python中,魔法函数是一类特殊的方法,它们以双下划线(__)开头和结尾,在特定情况下由Python解释器自动调用。这些方法被称为“魔法”,因为它们能够在不显式调用的情况下,在类定义中执行特定的操作。由于它们对于Python对象的行为具有隐式的影响,因此被称为“魔法”。

        魔法函数的存在使得Python类能够像内置数据类型一样进行操作,使得代码更加简洁、灵活,并且易于理解。通过合理地使用魔法函数,可以使得自定义的类更加符合Python的惯例和语言规范,同时提高代码的可读性和可维护性。

2、魔法函数的重要性

        Python魔法函数在编写面向对象的代码时至关重要。它们提供了一种简洁、优雅的方式来定制类的行为,使得用户能够更加灵活地使用和扩展已有的类。通过合理地使用魔法函数,用户可以使得自定义的类更加符合Python的惯例和语言规范,同时提高代码的可读性和可维护性。

3、简单示例说明魔法函数是如何工作的

        让我们通过一个简单的示例来说明魔法函数是如何工作的。假设我们有一个名为Point的类,用于表示二维平面上的点,并且我们想要定义一个魔法函数来计算两个点之间的距离。

import mathclass Point:def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return f"({self.x}, {self.y})"def distance_to(self, other_point):return math.sqrt((self.x - other_point.x)**2 + (self.y - other_point.y)**2)# 创建两个点对象
p1 = Point(0, 0)
p2 = Point(3, 4)# 输出点的字符串表示
print("Point 1:", p1)  # 输出:Point 1: (0, 0)
print("Point 2:", p2)  # 输出:Point 2: (3, 4)# 计算两点之间的距离
distance = p1.distance_to(p2)
print("Distance between points:", distance)  # 输出:Distance between points: 5.0

        在上面的示例中,我们定义了一个Point类,并实现了__init____str__distance_to等方法。其中,__init__方法用于初始化对象,__str__方法用于返回对象的字符串表示,distance_to方法用于计算两个点之间的距离。

        当我们使用print()函数输出点对象时,Python解释器会自动调用__str__方法来获取对象的字符串表示。而当我们调用p1.distance_to(p2)时,Python解释器会自动调用distance_to方法来计算两个点之间的距离。这些魔法函数的存在使得我们能够以一种更加直观和自然的方式操作对象,从而使得代码更加清晰和易于理解。

二、常用的魔法函数及其作用

下面将介绍一些常见的魔法函数以及对应的示例:

1、__init__(self, ...)

初始化对象。

class MyClass:def __init__(self, value):self.value = valueobj = MyClass(10)

2、__str__(self)

返回对象的字符串表示。

class MyClass:def __init__(self, value):self.value = valuedef __str__(self):return f"MyClass with value: {self.value}"obj = MyClass(10)
print(obj)  # 输出: MyClass with value: 10

3、__repr__(self)

返回对象的“官方”字符串表示,通常用于调试。

class MyClass:def __init__(self, value):self.value = valuedef __repr__(self):return f"MyClass({self.value})"obj = MyClass(10)
print(obj)  # 输出: MyClass(10)

4、__len__(self)

返回对象的长度。

class MyList:def __init__(self, items):self.items = itemsdef __len__(self):return len(self.items)my_list = MyList([1, 2, 3, 4])
print(len(my_list))  # 输出: 4

5、__getitem__(self, key)

获取对象的某个元素。

class MyList:def __init__(self, items):self.items = itemsdef __getitem__(self, index):return self.items[index]my_list = MyList([1, 2, 3, 4])
print(my_list[2])  # 输出: 3

6、__setitem__(self, key, value)

设置对象的某个元素。

class MyList:def __init__(self, items):self.items = itemsdef __setitem__(self, index, value):self.items[index] = valuemy_list = MyList([1, 2, 3, 4])
my_list[2] = 10
print(my_list.items)  # 输出: [1, 2, 10, 4]

7、__delitem__(self, key)

删除对象的某个元素。

class MyList:def __init__(self, items):self.items = itemsdef __delitem__(self, index):del self.items[index]my_list = MyList([1, 2, 3, 4])
del my_list[2]
print(my_list.items)  # 输出: [1, 2, 4]

8、__contains__(self, item)

判断对象是否包含某个元素。

class MyList:def __init__(self, items):self.items = itemsdef __contains__(self, item):return item in self.itemsmy_list = MyList([1, 2, 3, 4])
print(2 in my_list)  # 输出: True

9、__iter__(self)

返回迭代器对象,用于支持对象的迭代。

class MyList:def __init__(self, items):self.items = itemsdef __iter__(self):return iter(self.items)my_list = MyList([1, 2, 3, 4])
for item in my_list:print(item)  # 输出: 1 2 3 4

10、__next__(self)

迭代器的下一个元素。

class MyIterator:def __init__(self, data):self.data = dataself.index = 0def __iter__(self):return selfdef __next__(self):if self.index >= len(self.data):raise StopIterationresult = self.data[self.index]self.index += 1return resultmy_iterator = MyIterator([1, 2, 3, 4])
for item in my_iterator:print(item)  # 输出: 1 2 3 4

11、__call__(self, ...)

使对象可以像函数一样被调用。

class MyCallable:def __call__(self, x, y):return x + yadd = MyCallable()
print(add(3, 5))  # 输出: 8

12、__add__(self, other)

实现对象的加法。

class MyClass:def __init__(self, value):self.value = valuedef __add__(self, other):return self.value + otherobj = MyClass(10)
result = obj + 5
print(result)  # 输出: 15

13、__sub__(self, other)

实现对象的减法。

class MyClass:def __init__(self, value):self.value = valuedef __sub__(self, other):return self.value - otherobj = MyClass(10)
result = obj - 3
print(result)  # 输出: 7

14、__mul__(self, other)

实现对象的乘法。

class MyClass:def __init__(self, value):self.value = valuedef __mul__(self, other):return self.value * otherobj = MyClass(10)
result = obj * 2
print(result)  # 输出: 20

15、__truediv__(self, other)

实现对象的真除法。

class MyClass:def __init__(self, value):self.value = valuedef __truediv__(self, other):return self.value / otherobj = MyClass(10)
result = obj / 2
print(result)  # 输出: 5.0

16、__floordiv__(self, other)

实现对象的整除法。

class MyClass:def __init__(self, value):self.value = valuedef __floordiv__(self, other):return self.value // otherobj = MyClass(10)
result = obj // 3
print(result)  # 输出: 3

17、__mod__(self, other)

实现对象的取模运算。

class MyClass:def __init__(self, value):self.value = valuedef __mod__(self, other):return self.value % otherobj = MyClass(10)
result = obj % 3
print(result)  # 输出: 1

18、__pow__(self, other[, modulo])

实现对象的幂运算。

class MyClass:def __init__(self, value):self.value = valuedef __pow__(self, other, modulo=None):return self.value ** otherobj = MyClass(2)
result = obj ** 3
print(result)  # 输出: 8

19、__eq__(self, other)

实现对象的等于比较。

class MyClass:def __init__(self, value):self.value = valuedef __eq__(self, other):return self.value == otherobj = MyClass(10)
result = obj == 10
print(result)  # 输出: True

20、__ne__(self, other)

实现对象的不等于比较。

class MyClass:def __init__(self, value):self.value = valuedef __ne__(self, other):return self.value != otherobj = MyClass(10)
result = obj != 5
print(result)  # 输出: True

21、__lt__(self, other)

实现对象的小于比较。

class MyClass:def __init__(self, value):self.value = valuedef __lt__(self, other):return self.value < otherobj = MyClass(10)
result = obj < 15
print(result)  # 输出: True

22、__le__(self, other)

实现对象的小于等于比较。

class MyClass:def __init__(self, value):self.value = valuedef __le__(self, other):return self.value <= otherobj = MyClass(10)
result = obj <= 10
print(result)  # 输出: True

23、__gt__(self, other)

实现对象的大于比较。

class MyClass:def __init__(self, value):self.value = valuedef __gt__(self, other):return self.value > otherobj = MyClass(10)
result = obj > 5
print(result)  # 输出: True

24、__ge__(self, other)

实现对象的大于等于比较。

class MyClass:def __init__(self, value):self.value = valuedef __ge__(self, other):return self.value >= otherobj = MyClass(10)
result = obj >= 10
print(result)  # 输出: True

25、__hash__(self)

返回对象的哈希值,用于支持对象在字典等哈希表数据结构中的使用。

class MyClass:def __init__(self, value):self.value = valuedef __hash__(self):return hash(self.value)obj = MyClass(10)
print(hash(obj))  # 输出: 10

26、__bool__(self)

返回对象的布尔值,用于控制对象在布尔上下文中的行为。

class MyClass:def __init__(self, value):self.value = valuedef __bool__(self):return self.value > 0obj1 = MyClass(10)
obj2 = MyClass(0)
print(bool(obj1))  # 输出: True
print(bool(obj2))  # 输出: False

27、__getattr__(self, name)

获取对象的属性,当属性不存在时被调用。

class MyClass:def __init__(self, value):self.value = valuedef __getattr__(self, name):return f"Attribute {name} not found"obj = MyClass(10)
print(obj.foo)  # 输出: Attribute foo not found

28、__setattr__(self, name, value)

设置对象的属性。

class MyClass:def __init__(self, value):self.value = valuedef __setattr__(self, name, value):print(f"Setting attribute {name} to {value}")super().__setattr__(name, value)obj = MyClass(10)
obj.foo = 'bar'  # 输出: Setting attribute foo to bar

29、__delattr__(self, name)

删除对象的属性。

class MyClass:def __init__(self, value):self.value = valuedef __delattr__(self, name):print(f"Deleting attribute {name}")super().__delattr__(name)obj = MyClass(10)
del obj.value  # 输出: Deleting attribute value

30、__dir__(self)

返回对象的属性列表。

class MyClass:def __init__(self, value):self.value = valuedef __dir__(self):return ['value']obj = MyClass(10)
print(dir(obj))  # 输出: ['value']

31、__enter__(self)

进入上下文管理器时调用的方法,通常与 with 语句一起使用。

class MyResource:def __enter__(self):print("Entering the context")return selfdef __exit__(self, exc_type, exc_value, traceback):print("Exiting the context")with MyResource() as res:print("Inside the context")
# 输出:
# Entering the context
# Inside the context
# Exiting the context

32、__exit__(self, exc_type, exc_value, traceback)

退出上下文管理器时调用的方法,通常与 with 语句一起使用。

class MyResource:def __enter__(self):print("Entering the context")return selfdef __exit__(self, exc_type, exc_value, traceback):print("Exiting the context")with MyResource():print("Inside the context")
# 输出:
# Entering the context
# Inside the context
# Exiting the context

三、自定义魔法函数

        自定义魔法函数是通过在自定义类中定义特殊方法(以双下划线开头和结尾的方法)来实现的。这些魔法方法允许自定义类模拟内置类型的行为,例如算术运算、比较、字符串表示等。

下面是如何在自定义类中定义和使用自定义的魔法函数的详细介绍:

  1. 选择合适的魔法函数:首先,确定你想要模拟的内置类型行为,并选择适合的魔法函数。例如,如果你想要支持对象的加法运算,你可以实现 __add__ 方法。

  2. 在类中定义魔法函数:在自定义类中定义选定的魔法函数,并实现相应的逻辑。确保你的魔法函数接受适当数量的参数,并按照预期返回结果。

  3. 使用自定义的魔法函数:创建类的实例并使用定义的魔法函数来执行相应的操作。

下面是一个示例,展示如何在自定义类中实现自己的 __add____str__ 魔法函数:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):if isinstance(other, Point):# 如果 other 是 Point 类的实例,则执行向量加法return Point(self.x + other.x, self.y + other.y)elif isinstance(other, (int, float)):# 如果 other 是整数或浮点数,则执行标量加法return Point(self.x + other, self.y + other)else:# 其他情况下引发 TypeErrorraise TypeError("Unsupported operand type for +")def __str__(self):return f"({self.x}, {self.y})"# 创建两个 Point 对象
p1 = Point(1, 2)
p2 = Point(3, 4)# 使用 __add__ 进行向量加法
result_vector = p1 + p2
print("Vector Addition Result:", result_vector)  # 输出: Vector Addition Result: (4, 6)# 使用 __add__ 进行标量加法
result_scalar = p1 + 5
print("Scalar Addition Result:", result_scalar)  # 输出: Scalar Addition Result: (6, 7)

        在上面的示例中,我们定义了一个 Point 类,并在该类中实现了 __add__ 方法来支持向量加法和标量加法。同时,我们还实现了 __str__ 方法来返回对象的字符串表示。最后,我们创建了两个 Point 对象并进行加法运算,演示了自定义魔法函数的使用。

四、魔法函数的应用

        魔法函数在实际编程中有许多应用场景,它们可以使代码更加简洁、清晰和易于维护。下面是一些常见的魔法函数的实际应用和示例:

1、迭代器和可迭代对象

        通过实现 __iter____next__ 方法,可以将一个类变成可迭代对象或迭代器,使其能够被 for 循环等语句使用。

class MyRange:def __init__(self, start, end):self.start = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.start >= self.end:raise StopIterationcurrent = self.startself.start += 1return current# 使用自定义的迭代器
for num in MyRange(1, 5):print(num)  # 输出: 1 2 3 4

2、运算符重载

通过实现 __add____sub__ 等方法,可以使对象支持常见的算术运算,增强类的功能性。

class Vector:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):if isinstance(other, Vector):return Vector(self.x + other.x, self.y + other.y)else:raise TypeError("Unsupported operand type for +")# 使用自定义的运算符重载
v1 = Vector(1, 2)
v2 = Vector(3, 4)
result = v1 + v2
print(result.x, result.y)  # 输出: 4 6

3、上下文管理器

        通过实现 __enter____exit__ 方法,可以创建上下文管理器,用于资源管理和异常处理等场景。

class FileManager:def __init__(self, filename, mode):self.filename = filenameself.mode = modedef __enter__(self):self.file = open(self.filename, self.mode)return self.filedef __exit__(self, exc_type, exc_value, traceback):self.file.close()# 使用自定义的上下文管理器
with FileManager('example.txt', 'w') as f:f.write('Hello, world!')

4、属性访问控制

通过实现 __getattr____setattr__ 等方法,可以控制对象属性的访问、设置和删除。

class ProtectedAttributes:def __init__(self):self._protected = 0def __getattr__(self, name):if name == 'protected':raise AttributeError("This attribute is protected")else:return super().__getattr__(name)def __setattr__(self, name, value):if name == 'protected':raise AttributeError("Cannot set protected attribute")else:super().__setattr__(name, value)# 使用自定义的属性访问控制
obj = ProtectedAttributes()
obj.public = 1
print(obj.public)  # 输出: 1
obj.protected = 2  # 引发 AttributeError

        这些示例展示了魔法函数在实际编程中的应用,它们使得代码更加简洁、清晰和易于维护,同时也增强了类的功能性和灵活性。

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

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

相关文章

神器!!Python热重载调试【送源码】

在 Python 开发的路上&#xff0c;调试是我们不可避免的一环。 而今天推荐的开源项目Reloadium &#xff0c;让你在不重启程序的情况下实现代码的即时更新和调试。 &#x1f504; Reloadium 功能亮点&#xff1a; 1. 热重载魔法&#xff1a; Reloadium 不仅仅能够实现代码的…

电脑缺失msvcp120.dll要如何解决,学会这七个方法,轻松摆脱困扰

msvcp120.dll 是 Microsoft Visual C 2013 运行时库的一部分&#xff0c;它提供了 C 标准库的实现&#xff0c;使得开发者能够利用丰富的 C 功能来构建复杂的应用程序。这个文件对于使用了 C 标准库的应用程序来说是必不可少的。当这些应用程序运行时&#xff0c;它们会动态链接…

Docker管理工具Portainer忘记admin登录密码

停止Portainer容器 docker stop portainer找到portainer容器挂载信息 docker inspect portainer找到目录挂载信息 重置密码 docker run --rm -v /var/lib/docker/volumes/portainer_data/_data:/data portainer/helper-reset-password生成新的admin密码&#xff0c;使用新密…

Ubuntu安装GCC编译器

GCC编译器安装 GCC编译器安装切换软件源(换成国内的服务器)1 、创建一个文本文档并命名为“sources.list”2 、复制软件源列表清华源:阿里源:3 、把修改之后的.list 文件覆盖原有的文件4 、更新软件列表5 、安装6 、检查是否安装成功7、GCC 编译器:GCC编译器安装 这里演示…

cdo | 常用命令

整理一下平时经常会使用的cdo命令 如何来更改netcdf数据中的变量名呢&#xff1f; 假设我现在有一个sst月平均数据,希望将里面的变量名称sst修改为sst_new netcdf oisst_monthly { dimensions:lat 180 ;lon 360 ;time UNLIMITED ; // (476 currently)nbnds 2 ; variable…

【PTA】7-4 朋友圈(C++ * 并查集思想)代码实现 一点反思

题目如下&#xff1a; AC代码如下&#xff08;参考PTA 7-2 朋友圈&#xff08;25 分&#xff09;_处理微信消息pta-CSDN博客&#xff09; #include<bits/stdc.h> using namespace std; #define sz 30005 typedef struct node{int rk, fa; }Node; Node tree[sz]; void In…

STL:copy简介

STL:copy STL算法&#xff1a;copy std::copy()函数使用 std::copy 函数在 中声明&#xff0c;属于变易算法(Modifying sequence operations)&#xff0c;主要用于实现序列数据的复制 template <class InputIterator, class OutputIterator>OutputIterator copy (InputI…

【SQL学习进阶】从入门到高级应用(九)

文章目录 子查询什么是子查询where后面使用子查询from后面使用子查询select后面使用子查询exists、not existsin和exists区别 union&union alllimit &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f495;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面…

【IB Protocal Serial--WQE】

IB Protocal Serial--WQE 1 Intro1.1 What1.2 IBA WQE 本系列文章介绍RDMA技术的具体实现–InfiniBand Protocal&#xff1b; Introduce the features, capalities,components, and elements of IBA. the principles of operation. 1 Intro 1.1 What 理解IB协议下面这三句话对…

CSS--学习

CSS 1简介 1.1定义 层叠样式表 (Cascading Style Sheets&#xff0c;缩写为 CSS&#xff09;&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09;。 1.2 特性 继承性 子级默认继承父级的文字控制属性。层叠性 相同的属性…

基于RFID技术的烟草在线监测系统在烟草仓库温湿度监测中的应用。

在现代工业生产中&#xff0c;精准高效的在线监测系统对于产品质量控制至关重要。尤其是在高价值且对环境敏感的产品制造过程中&#xff0c;如烟草加工&#xff0c;实时准确的数据采集与分析直接关系到最终产品的品质及安全标准达标程度。 烟草行业在我国属于传统轻工业之一&am…

Vite项目构建chrome extension,实现多入口

本项目使用Vite5 Vue3进行构建。 要使用vite工程构建浏览器插件&#xff0c;无非就是要实现popup页面和options页面。这就需要在项目中用到多入口打包&#xff08;生成多个html文件&#xff09;。 实现思路&#xff1a; 通过配置vite工程&#xff0c;使得项目打包后有两个h…

Spring中的Aware接口

Spring中的Aware接口 Aware接口介绍 Aware是Spring中的接口&#xff0c;它的作用是可以让Bean获取到运行环境的相关信息。比如获取到上下文、Bean在容器中的名称等。 Spring中提供了很多Aware接口的子类&#xff0c;具体如下&#xff1a; 常用接口的作用如下&#xff1a; …

【网络原理】HTTP|认识请求“报头“|Host|Content-Length|Content-Type|UA|Referer|Cookie

目录 认识请求"报头"(header) Host Content-Length Content-Type User-Agent(简称UA) Referer &#x1f4a1;Cookie&#xff08;最重要的一个header&#xff0c;开发&面试高频问题&#xff09; 1.Cookie是啥&#xff1f; 2.Cookie怎么存的&#xff1f; …

视频汇聚EasyCVR视频监控云平台对接GA/T 1400视图库对象和对象集合XMLSchema描述

GA/T 1400协议主要应用于公安系统的视频图像信息应用系统&#xff0c;如警务综合平台、治安防控系统、交通管理系统等。在城市的治安监控、交通管理、案件侦查等方面&#xff0c;GA/T 1400协议都发挥着重要作用。 以视频汇聚EasyCVR视频监控资源管理平台为例&#xff0c;该平台…

游戏逆向工具分析及解决方案

游戏逆向&#xff0c;是指通过各类工具对游戏进行反编译及源码分析&#xff0c;尝试分析游戏的实现逻辑的过程。这个过程需要使用解密、反编译、解压缩等技术&#xff0c;目的是还原或分析出游戏的代码逻辑及资源。 游戏逆向工具可以按照不同功能进行划分&#xff0c;如&#…

java微服在使用nacos注册中心时,ribbon负载均衡时给部分feign client使用静态serverList

我看很多贴子都是针对eureka环境下做静态ServerList配置&#xff0c;目前国内大部分都用Nacos&#xff0c;所以便研究了一下。 micore-service-x:ribbon:listOfServers: ip1:port,ip2:port2NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList m…

Linux上传文件

在finalshell中连接的Linux系统中&#xff0c;输入命令rz然后选择windows中的文件即可。

数据结构算法 数组的实现与练习(C语言实现,Java实现)

文章目录 数据结构数组(顺序表)特点使用Java实现更高级的数组C语言实现总结优点缺点 例题[26. 删除有序数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)[1. 两数之和](https://leetcode.cn/problems/two-sum/)[27. 移除元素](https://lee…

破解生产难题,这些中小汽配企业这样做

伴随着汽车新四化即智能化、网联化、电动化、共享化的趋势,国内汽车零部件行业在市场规模和发展速度上呈现高速增长。然而&#xff0c;在劳动力成本上升,原材料价格上涨,企业生产成本逐年增加的情境下&#xff0c;市场竞争越来越激烈&#xff0c;如何降本增效&#xff0c;还能构…