目录
![]()
![]()
![]()
一、概述
1、定义
魔法方法(Magic Methods/Special Methods,也称特殊方法或双下划线方法)是Python中一类具有特殊命名规则的方法,它们的名称通常以双下划线(`__`)开头和结尾。
魔法方法用于在特定情况下自动被Python解释器调用,而不需要显式地调用它们,它们提供了一种机制,让你可以定义自定义类时具有与内置类型相似的行为。
2、作用
魔法方法允许开发者重载Python中的一些内置操作或函数的行为,从而为自定义的类添加特殊的功能。
二、应用场景
1、构造和析构
1-1、__init__(self, [args...]):在创建对象时初始化属性。
1-2、__new__(cls, [args...]):在创建对象时控制实例的创建过程(通常与元类一起使用)。
1-3、__del__(self):在对象被销毁前执行清理操作,如关闭文件或释放资源。
2、操作符重载
2-1、__add__(self, other)、__sub__(self, other)、__mul__(self, other)等:自定义对象之间的算术运算。
2-2、__eq__(self, other)、__ne__(self, other)、__lt__(self, other)等:定义对象之间的比较操作。
3、字符串和表示
3-1、__str__(self):定义对象的字符串表示,常用于print()函数。
3-2、__repr__(self):定义对象的官方字符串表示,用于repr()函数和交互式解释器。
4、容器管理
4-1、__getitem__(self, key)、__setitem__(self, key, value)、__delitem__(self, key):用于实现类似列表或字典的索引访问、设置和删除操作。
4-2、__len__(self):返回对象的长度或元素个数。
5、可调用对象
5-1、__call__(self, [args...]):允许对象像函数一样被调用。
6、上下文管理
6-1、__enter__(self)、__exit__(self, exc_type, exc_val, exc_tb):用于实现上下文管理器,如with语句中的对象。
7、属性访问和描述符
7-1、__getattr__, __setattr__, __delattr__:这些方法允许对象在访问或修改不存在的属性时执行自定义操作。
7-2、描述符(Descriptors)是实现了__get__, __set__, 和__delete__方法的对象,它们可以控制对另一个对象属性的访问。
8、迭代器和生成器
8-1、__iter__和__next__:这些方法允许对象支持迭代操作,如使用for循环遍历对象。
8-2、__aiter__, __anext__:这些是异步迭代器的魔法方法,用于支持异步迭代。
9、数值类型
9-1、__int__(self)、__float__(self)、__complex__(self):定义对象到数值类型的转换。
9-2、__index__(self):定义对象用于切片时的整数转换。
10、复制和序列化
10-1、__copy__和__deepcopy__:允许对象支持浅复制和深复制操作。
10-2、__getstate__和__setstate__:用于自定义对象的序列化和反序列化过程。
11、自定义元类行为
11-1、__metaclass__(Python 2)或元类本身(Python 3):允许自定义类的创建过程,如动态创建类、修改类的定义等。
12、自定义类行为
12-1、__init__和__new__:用于初始化对象或控制对象的创建过程。
12-2、__init_subclass__:在子类被创建时调用,允许在子类中执行一些额外的操作。
13、类型检查和转换
13-1、__instancecheck__和__subclasscheck__:用于自定义isinstance()和issubclass()函数的行为。
14、自定义异常
14-1、你可以通过继承内置的Exception类来创建自定义的异常类,并定义其特定的行为。
![]()
三、学习方法
要学好Python的魔法方法,你可以遵循以下方法及步骤:
1、理解基础
首先确保你对Python的基本语法、数据类型、类和对象等概念有深入的理解,这些是理解魔法方法的基础。
2、查阅文档
仔细阅读Python官方文档中关于魔法方法的部分,文档会详细解释每个魔法方法的作用、参数和返回值。你可以通过访问Python的官方网站或使用help()函数在Python解释器中查看文档。
3、编写示例
为每个魔法方法编写简单的示例代码,以便更好地理解其用法和效果,通过实际编写和运行代码,你可以更直观地感受到魔法方法如何改变对象的行为。
4、实践应用
在实际项目中尝试使用魔法方法。如,你可以创建一个自定义的集合类,使用__getitem__、__setitem__和__delitem__方法来实现索引操作。只有通过实践应用,你才能更深入地理解魔法方法的用途和重要性。
5、阅读他人代码
阅读开源项目或他人编写的代码,特别是那些使用了魔法方法的代码,这可以帮助你学习如何在实际项目中使用魔法方法。通过分析他人代码中的魔法方法使用方式,你可以学习到一些新的技巧和最佳实践。
6、参加社区讨论
参与Python社区的讨论,与其他开发者交流关于魔法方法的使用经验和技巧,在社区中提问或回答关于魔法方法的问题,这可以帮助你更深入地理解魔法方法并发现新的应用场景。
7、持续学习
Python语言和其生态系统不断发展,新的魔法方法和功能可能会不断被引入,保持对Python社区的关注,及时学习新的魔法方法和最佳实践。
8、练习与总结
多做练习,通过编写各种使用魔法方法的代码来巩固你的理解,定期总结你学到的知识和经验,形成自己的知识体系。
9、注意兼容性
在使用魔法方法时,要注意不同Python版本之间的兼容性差异,确保你的代码在不同版本的Python中都能正常工作。
10、避免过度使用
虽然魔法方法非常强大,但过度使用可能会导致代码难以理解和维护,在编写代码时,要权衡使用魔法方法的利弊,避免滥用。
总之,学好Python的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。
![]()
四、魔法方法
53、__or__方法
53-1、语法
- __or__(self, other, /)
- Return self | other
53-2、参数
53-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
53-2-2、 other(必须):表示要对self对象执行按位或操作的对象。
53-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
53-3、功能
用于定义对象之间的按位或(bitwise OR)操作。
53-4、返回值
返回一个表示self和other之间按位或操作结果的对象。
53-5、说明
无
53-6、用法
- # 053、__or__方法:
- # 1、简单整数类
- class IntWrapper:
- def __init__(self, value):
- self.value = value
- def __or__(self, other):
- if not isinstance(other, IntWrapper):
- raise TypeError("Unsupported operand types")
- return IntWrapper(self.value | other.value)
- def __repr__(self):
- return f"IntWrapper({self.value})"
-
- # 2、权限标志类
- class Permission:
- READ = 1
- WRITE = 2
- EXECUTE = 4
- def __init__(self, flags):
- self.flags = flags
- def __or__(self, other):
- return Permission(self.flags | other.flags)
- def __repr__(self):
- return f"Permission({self.flags})"
-
- # 3、颜色混合(RGB 示例)
- class RGBColor:
- def __init__(self, r, g, b):
- self.r = r
- self.g = g
- self.b = b
- def __or__(self, other):
- return RGBColor(self.r | other.r, self.g | other.g, self.b | other.b) # 注意:这不一定是颜色混合的合理方式
- def __repr__(self):
- return f"RGBColor({self.r}, {self.g}, {self.b})"
-
- # 4、时间范围合并
- from datetime import datetime, timedelta
- class TimeRange:
- def __init__(self, start, end):
- self.start = start
- self.end = end
- def __or__(self, other):
- # 简化的合并逻辑,仅适用于不重叠且按时间顺序排列的范围
- if self.end <= other.start:
- return TimeRange(self.start, max(self.end, other.end))
- raise ValueError("Ranges overlap or are not in order")
- def __repr__(self):
- return f"TimeRange({self.start}, {self.end})"
-
- # 5、集合类似物的合并
- class UniqueList:
- def __init__(self, items):
- self.items = list(set(items))
- def __or__(self, other):
- return UniqueList(self.items + list(set(other.items) - set(self.items)))
- def __repr__(self):
- return f"UniqueList({self.items})"
-
- # 6、图形界面的按钮状态
- class ButtonState:
- PRESSED = 1
- RELEASED = 0
- def __init__(self, state):
- self.state = state
- def __or__(self, other):
- # 假设这里是一个特殊的逻辑,例如“同时按下多个按钮”
- return ButtonState(self.state | other.state)
- def __repr__(self):
- return f"ButtonState({self.state})"
-
- # 7、网络包合并(简化示例)
- class Packet:
- def __init__(self, data):
- self.data = data
- def __or__(self, other):
- return Packet(self.data + other.data)
- def __repr__(self):
- return f"Packet({self.data})"
-
- # 8、选项类(例如命令行选项)
- class Option:
- A = 1
- B = 2
- def __init__(self, flags):
- self.flags = flags
- def __or__(self, other):
- return Option(self.flags | other.flags)
- def __repr__(self):
- return f"Option({self.flags})"
-
- # 9、游戏状态合并(例如合并两个玩家的状态)
- class GameState:
- def __init__(self, score, lives):
- self.score = score
- self.lives = lives
- def __or__(self, other):
- # 假设合并状态是取最高分和总生命数(不实际,仅为示例)
- return GameState(max(self.score, other.score), self.lives + other.lives)
- def __repr__(self):
- return f"GameState(score={self.score}, lives={self.lives})"
-
- # 10、自定义的数据结构合并(例如合并两个自定义字典)
- class CustomDict:
- def __init__(self, data):
- self.data = data
- def __or__(self, other):
- return CustomDict({**self.data, **other.data})
- def __repr__(self):
- return f"CustomDict({self.data})"
- if __name__ == '__main__':
- dict1 = CustomDict({"a": 1, "b": 2})
- dict2 = CustomDict({"b": 3, "c": 4})
- merged_dict = dict1 | dict2
- print(merged_dict) # 输出:CustomDict({'a': 1, 'b': 3, 'c': 4})
-
- # 11、版本控制合并(模拟两个软件版本的合并)
- class Version:
- def __init__(self, major, minor, patch):
- self.major = major
- self.minor = minor
- self.patch = patch
- def __or__(self, other):
- # 在这个例子中,我们简单地取两个版本中的最大值作为合并后的版本
- # 在实际的版本控制系统中,合并版本会更为复杂
- return Version(
- max(self.major, other.major),
- max(self.minor, other.minor),
- max(self.patch, other.patch)
- )
- def __repr__(self):
- return f"Version({self.major}.{self.minor}.{self.patch})"
- if __name__ == '__main__':
- v1 = Version(1, 2, 3)
- v2 = Version(1, 3, 1)
- merged_version = v1 | v2
- print(merged_version) # 输出:Version(1.3.3)
-
- # 12、图形路径合并(例如合并两个图形路径以创建复杂形状)
- class Path:
- def __init__(self, points):
- self.points = points
- def __or__(self, other):
- # 合并两个路径,简单地将它们的点连接起来(注意:这不会创建有效的图形路径)
- return Path(self.points + other.points)
- def __repr__(self):
- return f"Path({self.points})"
- if __name__ == '__main__':
- path1 = Path([(0, 0), (1, 1), (2, 0)])
- path2 = Path([(2, 0), (3, 1), (4, 0)])
- combined_path = path1 | path2
- print(combined_path) # 输出:Path([(0, 0), (1, 1), (2, 0), (2, 0), (3, 1), (4, 0)])
54、__pos__方法
54-1、语法
- __pos__(self, /)
- + self
54-2、参数
54-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
54-2-2、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
54-3、功能
用于定义当对象被一元正号(+)运算符作用时的行为。
54-4、返回值
返回一个对象,该对象代表了对原始对象应用一元正号运算符后的结果。
54-5、说明
无
54-6、用法
- # 054、__pos__方法:
- # 1、简单数值类
- class Number:
- def __init__(self, value):
- self.value = value
- def __pos__(self):
- return Number(self.value) # 通常不会改变值,但为了演示
- def __repr__(self):
- return f"Number({self.value})"
- if __name__ == '__main__':
- n = Number(5)
- print(+n) # 输出: Number(5)
-
- # 2、复数类
- class ComplexNumber:
- def __init__(self, real, imag):
- self.real = real
- self.imag = imag
- def __pos__(self):
- return self # 复数取正还是它本身
- def __repr__(self):
- return f"ComplexNumber({self.real},{self.imag})"
- if __name__ == '__main__':
- cn = ComplexNumber(1, 2)
- print(+cn) # 输出: ComplexNumber(1,2)
-
- # 3、向量类
- class Vector2D:
- def __init__(self, x, y):
- self.x = x
- self.y = y
- def __pos__(self):
- return self # 向量取正还是它本身
- def __repr__(self):
- return f"Vector2D({self.x},{self.y})"
- if __name__ == '__main__':
- v = Vector2D(3, 4)
- print(+v) # 输出: Vector2D(3,4)
-
- # 4、温度类(摄氏度)
- class Temperature:
- def __init__(self, celsius):
- self.celsius = celsius
- def __pos__(self):
- return self # 温度取正还是它本身
- def __repr__(self):
- return f"{self.celsius}°C"
- if __name__ == '__main__':
- t = Temperature(25)
- print(+t) # 输出: 25°C
-
- # 5、自定义字符串类
- class CustomString:
- def __init__(self, s):
- self.s = s
- def __pos__(self):
- return self # 字符串取正还是它本身
- def __str__(self):
- return self.s
- if __name__ == '__main__':
- cs = CustomString("Myelsa")
- print(+cs) # 输出: Myelsa
-
- # 6、时间类
- from datetime import datetime
- class Time:
- def __init__(self, dt):
- self.dt = dt
- def __pos__(self):
- return self # 时间取正还是它本身
- def __repr__(self):
- return self.dt.strftime("%H:%M:%S")
- if __name__ == '__main__':
- t = Time(datetime.now())
- print(+t) # 输出当前时间,如: 16:59:58
-
- # 7、货币类
- class Money:
- def __init__(self, amount, currency):
- self.amount = amount
- self.currency = currency
- def __pos__(self):
- return self # 货币取正还是它本身
- def __repr__(self):
- return f"{self.amount} {self.currency}"
- if __name__ == '__main__':
- m = Money(100, "USD")
- print(+m) # 输出: 100 USD
-
- # 8、分数类
- from fractions import Fraction
- class FractionWrapper:
- def __init__(self, numerator, denominator):
- self.fraction = Fraction(numerator, denominator)
- def __pos__(self):
- return FractionWrapper(self.fraction.numerator, self.fraction.denominator) # 包装器取正还是它本身
- def __repr__(self):
- return str(self.fraction)
- if __name__ == '__main__':
- f = FractionWrapper(1, 2)
- print(+f) # 输出: 1/2
-
- # 9、矩阵类(2x2)
- class Matrix2x2:
- def __init__(self, a, b, c, d):
- self.a = a
- self.b = b
- self.c = c
- self.d = d
- def __pos__(self):
- return Matrix2x2(self.a, self.b, self.c, self.d) # 矩阵取正还是它本身
- def __repr__(self):
- return f"[[{self.a}, {self.b}], [{self.c}, {self.d}]]"
- if __name__ == '__main__':
- m = Matrix2x2(1, 2, 3, 4)
- print(+m) # 输出: [[1, 2], [3, 4]]
-
- # 10、有理数类
- class Rational:
- def __init__(self, numerator, denominator=1):
- self.numerator = numerator
- self.denominator = denominator if denominator != 0 else 1
- self.simplify()
- def simplify(self):
- # 这里省略了简化分数的逻辑
- pass
- def __pos__(self):
- return Rational(self.numerator, self.denominator) # 有理数取正还是它本身
- def __repr__(self):
- return f"{self.numerator}/{self.denominator}"
- if __name__ == '__main__':
- r = Rational(3, 2)
- print(+r) # 输出: 3/2
-
- # 11、坐标点类(三维)
- class Point3D:
- def __init__(self, x, y, z):
- self.x = x
- self.y = y
- self.z = z
- def __pos__(self):
- return Point3D(self.x, self.y, self.z) # 坐标点取正还是它本身
- def __repr__(self):
- return f"({self.x}, {self.y}, {self.z})"
- if __name__ == '__main__':
- p = Point3D(1, 2, 3)
- print(+p) # 输出: (1, 2, 3)
-
- # 12、四元数类
- class Quaternion:
- def __init__(self, w, x, y, z):
- self.w = w
- self.x = x
- self.y = y
- self.z = z
- def __pos__(self):
- return Quaternion(self.w, self.x, self.y, self.z) # 四元数取正还是它本身
- def __repr__(self):
- return f"({self.w}, {self.x}, {self.y}, {self.z})"
- if __name__ == '__main__':
- q = Quaternion(1, 0, 0, 0)
- print(+q) # 输出: (1, 0, 0, 0)
55、__pow__方法
55-1、语法
- __pow__(self, other, mod=None, /)
- Return pow(self, other, mod)
55-2、参数
55-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
55-2-2、 other(必须):表示要用于幂运算的指数。
55-2-3、mod(可选):如果提供了这个参数,则执行模幂运算。
55-2-4、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
55-3、功能
用于定义对象之间的幂运算(**)以及模幂运算(pow(x, y, z))。
55-4、返回值
返回一个对象,该对象代表了对self对象应用幂运算(或模幂运算)后的结果。
55-5、说明
在pow(x, y, z)中, x是self,y是other,而z是mod。如果不提供mod(即mod=None),则执行普通的幂运算。
55-6、用法
- # 055、__pow__方法:
- # 1、简单数值类
- class SimpleNumber:
- def __init__(self, value):
- self.value = value
- def __pow__(self, other, mod=None):
- if mod is None:
- return SimpleNumber(self.value ** other)
- return SimpleNumber(pow(self.value, other, mod))
- def __repr__(self):
- return f"SimpleNumber({self.value})"
- if __name__ == '__main__':
- num = SimpleNumber(2)
- print(num ** 3) # 输出: SimpleNumber(8)
- print(num.__pow__(10, 7)) # 输出: SimpleNumber(2),直接调用__pow__方法并传入模数
-
- # 2、矩阵类(2x2)
- import numpy as np
- class Matrix2x2:
- def __init__(self, data):
- self.data = np.array(data, dtype=float).reshape(2, 2)
- def __pow__(self, other, mod=None):
- if mod is not None:
- raise NotImplementedError("Modulo not supported for matrices")
- return Matrix2x2(np.linalg.matrix_power(self.data, other))
- def __repr__(self):
- return f"Matrix2x2(\n{self.data}\n)"
- if __name__ == '__main__':
- m = Matrix2x2([[1, 2], [3, 4]])
- print(m ** 2) # 输出矩阵的平方
-
- # 3、时间单位的幂运算
- class TimeUnit:
- def __init__(self, seconds):
- self.seconds = seconds
- def __pow__(self, other, mod=None):
- # 时间单位取幂在物理上没有意义,但这里假设表示时间间隔的重复
- return TimeUnit(self.seconds * other)
- def __repr__(self):
- return f"TimeUnit({self.seconds} seconds)"
- if __name__ == '__main__':
- time = TimeUnit(60) # 1分钟
- print(time ** 3) # 输出: TimeUnit(180 seconds),即3分钟
-
- # 4、自定义单位类(如米的n次方)
- class UnitMeter:
- def __init__(self, value):
- self.value = value
- def __pow__(self, other, mod=None):
- # 米的n次方在物理上可能表示体积、面积等
- return UnitMeterPower(self.value, other)
- def __repr__(self):
- return f"UnitMeter({self.value} m)"
- class UnitMeterPower:
- def __init__(self, base_value, exponent):
- self.base_value = base_value
- self.exponent = exponent
- def __repr__(self):
- return f"UnitMeter^{self.exponent}({self.base_value} m)"
- if __name__ == '__main__':
- meter = UnitMeter(1)
- print(meter ** 3) # 输出: UnitMeter^3(1 m)
-
- # 5、复数类
- class ComplexNumber:
- def __init__(self, real, imag):
- self.real = real
- self.imag = imag
- def __pow__(self, other):
- # 假设other是实数或另一个复数
- # 这里简化处理,只处理实数幂
- if isinstance(other, int) or isinstance(other, float):
- magnitude = (self.real ** 2 + self.imag ** 2) ** (other / 2)
- angle = (other * math.atan2(self.imag, self.real)) % (2 * math.pi)
- return ComplexNumber(magnitude * math.cos(angle), magnitude * math.sin(angle))
- else:
- raise TypeError("Power must be a real number.")
- def __repr__(self):
- return f"ComplexNumber({self.real}+{self.imag}j)"
- if __name__ == '__main__':
- import math
- c = ComplexNumber(1, 1)
- print(c ** 2) # 输出:ComplexNumber(1.2246467991473532e-16+2.0j)
-
- # 6、坐标点类(二维空间)
- class Point2D:
- def __init__(self, x, y):
- self.x = x
- self.y = y
- def __pow__(self, other):
- # 这里的幂运算被重新定义为距离的平方(欧氏距离)
- return self.x ** 2 + self.y ** 2
- def __repr__(self):
- return f"Point2D({self.x},{self.y})"
- if __name__ == '__main__':
- p = Point2D(3, 4)
- print(p ** 2) # 输出: 25,表示点(3,4)到原点的距离的平方
-
- # 7、图形变换类(缩放)
- class ScaleTransform:
- def __init__(self, scale_factor):
- self.scale_factor = scale_factor
- def __pow__(self, other):
- # 幂运算表示连续的缩放
- return ScaleTransform(self.scale_factor ** other)
- def apply_to(self, point):
- # 假设point有x和y属性
- return Point2D(point.x * self.scale_factor, point.y * self.scale_factor)
- def __repr__(self):
- return f"ScaleTransform({self.scale_factor})"
- if __name__ == '__main__':
- scale = ScaleTransform(2)
- print(scale ** 3) # 输出: ScaleTransform(8),表示连续三次放大2倍
-
- # 8、自定义向量类
- class Vector:
- def __init__(self, *components):
- self.components = components
- def __pow__(self, other):
- # 假设other是整数,表示向量的点积自乘
- if isinstance(other, int):
- return Vector(*[comp ** other for comp in self.components])
- else:
- raise TypeError("Power must be an integer.")
- def __repr__(self):
- return f"Vector({', '.join(map(str, self.components))})"
- if __name__ == '__main__':
- v = Vector(1, 2, 3)
- print(v ** 2) # 输出: Vector(1, 4, 9),表示每个分量都平方了
评论记录:
回复评论: