目录
![]()
![]()
![]()
一、概述
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的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。
![]()
四、魔法方法
41、__xor__方法
41-1、语法
- __xor__(self, other, /)
- Return self ^ other
41-2、参数
41-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
41-2-2、 other(必须):表示要与self进行异或运算的第二个对象,即__xor__ 法操作的右侧操作数。
41-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
41-3、功能
用于实现自定义类型的异或(XOR)运算操作。
41-4、返回值
返回一个与self和other进行异或运算后的结果。
41-5、说明
无
41-6、用法
- # 041、__xor__方法:
- # 1、基本整数异或
- class MyInt:
- def __init__(self, value):
- self.value = value
- def __xor__(self, other):
- if not isinstance(other, MyInt):
- raise TypeError("Unsupported operand type(s) for ^: 'MyInt' and '{}'".format(type(other).__name__))
- return MyInt(self.value ^ other.value)
- def __repr__(self):
- return f"MyInt({self.value})"
- if __name__ == '__main__':
- a = MyInt(5)
- b = MyInt(3)
- print(a ^ b) # 输出: MyInt(6)
-
- # 2、字符串异或(假设为二进制字符串)
- class BinaryString:
- def __init__(self, value):
- if not all(c in '01' for c in value):
- raise ValueError("Value must contain only '0' and '1'.")
- self.value = value
- def __xor__(self, other):
- if not isinstance(other, BinaryString):
- raise TypeError("Unsupported operand type(s) for ^: 'BinaryString' and '{}'".format(type(other).__name__))
- if len(self.value) != len(other.value):
- raise ValueError("Strings must have the same length.")
- return BinaryString(''.join('1' if a != b else '0' for a, b in zip(self.value, other.value)))
- def __repr__(self):
- return f"BinaryString('{self.value}')"
- if __name__ == '__main__':
- a = BinaryString('1010')
- b = BinaryString('1100')
- print(a ^ b) # 输出: BinaryString('0110')
-
- # 3、列表异或(元素比较)
- class ListXOR:
- def __init__(self, value):
- self.value = value
- def __xor__(self, other):
- if not isinstance(other, ListXOR):
- raise TypeError("Unsupported operand type(s) for ^: 'ListXOR' and '{}'".format(type(other).__name__))
- return ListXOR(
- [x for x in self.value if x not in other.value] + [x for x in other.value if x not in self.value])
- def __repr__(self):
- return f"ListXOR({self.value})"
- if __name__ == '__main__':
- a = ListXOR([1, 2, 3])
- b = ListXOR([2, 3, 4])
- print(a ^ b) # 输出: ListXOR([1, 4])
-
- # 4、自定义向量类异或
- class Vector:
- def __init__(self, x, y):
- self.x = x
- self.y = y
- def __xor__(self, other):
- if not isinstance(other, Vector):
- raise TypeError("Unsupported operand type(s) for ^: 'Vector' and '{}'".format(type(other).__name__))
- # 假设这里我们返回两个向量对应分量的差的绝对值
- return Vector(abs(self.x - other.x), abs(self.y - other.y))
- def __repr__(self):
- return f"Vector({self.x}, {self.y})"
- if __name__ == '__main__':
- a = Vector(1, 2)
- b = Vector(3, 1)
- print(a ^ b) # 输出: Vector(2, 1)
-
- # 5、自定义状态机异或(表示状态切换)
- class State:
- def __init__(self, name):
- self.name = name
- def __xor__(self, other):
- if not isinstance(other, State):
- raise TypeError("Unsupported operand type(s) for ^: 'State' and '{}'".format(type(other).__name__))
- # 假设这里我们有一个固定的状态切换逻辑
- if self.name == 'A' and other.name == 'B':
- return State('C')
- elif self.name == 'B' and other.name == 'A':
- return State('D')
- # ... 其他情况可以添加更多逻辑
- raise ValueError("Invalid state transition")
- def __repr__(self):
- return f"State({self.name})"
- if __name__ == '__main__':
- a = State('A')
- b = State('B')
- print(a ^ b) # 输出: State(C)
-
- # 6、自定义权限类异或(表示权限的合并或排除)
- class Permission:
- def __init__(self, name, value):
- self.name = name
- self.value = value
- def __xor__(self, other):
- if not isinstance(other, Permission):
- raise TypeError("Unsupported operand type(s) for ^: 'Permission' and '{}'".format(type(other).__name__))
- # 假设这里的异或操作是返回两个权限值的按位异或
- return Permission(self.name + '^' + other.name, self.value ^ other.value)
- def __repr__(self):
- return f"Permission({self.name}, {self.value})"
- if __name__ == '__main__':
- read = Permission('READ', 1)
- write = Permission('WRITE', 2)
- print(read ^ write) # 输出可能是 Permission(READ^WRITE, 3),但具体取决于value的类型和表示
-
- # 7、自定义集合类异或(表示集合的对称差集)
- class CustomSet:
- def __init__(self, elements=None):
- if elements is None:
- self.elements = set()
- else:
- self.elements = set(elements)
- def __xor__(self, other):
- if not isinstance(other, CustomSet):
- raise TypeError("Unsupported operand type(s) for ^: 'CustomSet' and '{}'".format(type(other).__name__))
- # 返回两个集合的对称差集
- return CustomSet(self.elements ^ other.elements)
- def __repr__(self):
- return f"CustomSet({self.elements})"
- if __name__ == '__main__':
- set1 = CustomSet([1, 2, 3])
- set2 = CustomSet([2, 3, 4])
- print(set1 ^ set2) # 输出: CustomSet({1, 4})
-
- # 8、自定义整数范围类异或(表示两个整数范围的重叠部分)
- class Range:
- def __init__(self, start, end):
- self.start = start
- self.end = end
- def __xor__(self, other):
- if not isinstance(other, Range):
- raise TypeError("Unsupported operand type(s) for ^: 'Range' and '{}'".format(type(other).__name__))
- # 这里的异或操作表示返回两个范围不重叠的部分,可能需要更复杂的逻辑来处理各种边界情况
- # 这里只提供一个简化的示例
- if self.start > other.end or self.end < other.start:
- # 没有重叠,返回两个范围本身
- return [self, other]
- else:
- # 有重叠,需要更复杂的逻辑来处理
- # 这里简化为只返回第一个范围(仅为示例)
- return [self]
- def __repr__(self):
- return f"Range({self.start}, {self.end})"
- if __name__ == '__main__':
- range1 = Range(3, 6)
- range2 = Range(5, 11)
- print(range1 ^ range2) # 输出: [Range(3, 6)]
42、__le__方法
42-1、语法
- __le__(self, other, /)
- Return self <= other
42-2、参数
42-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
42-2-2、 other(必须):与self进行比较的另一个对象。
42-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
42-3、功能
用于定义对象之间的“小于或等于”比较操作。
42-4、返回值
返回一个布尔值(True或False),表示self是否小于或等于other。
42-5、说明
当你使用<=运算符时,other就是运算符右边的对象。
42-6、用法
- # 042、__le__方法:
- # 1、整数比较
- class MyInt:
- def __init__(self, value):
- self.value = value
- def __le__(self, other):
- if isinstance(other, MyInt):
- return self.value <= other.value
- elif isinstance(other, int):
- return self.value <= other
- else:
- return NotImplemented
- if __name__ == '__main__':
- a = MyInt(5)
- b = MyInt(10)
- print(a <= b) # True
- print(a <= 5) # True
-
- # 2、字符串长度比较
- class MyString:
- def __init__(self, value):
- self.value = value
- def __len__(self):
- return len(self.value)
- def __le__(self, other):
- if isinstance(other, MyString):
- return len(self) <= len(other)
- elif isinstance(other, (str, int)):
- return len(self.value) <= len(str(other))
- else:
- return NotImplemented
- if __name__ == '__main__':
- s1 = MyString("hello")
- s2 = MyString("world")
- print(s1 <= s2) # True
- print(s1 <= "hi") # False
-
- # 3、分数比较
- from fractions import Fraction
- class MyFraction:
- def __init__(self, numerator, denominator):
- self.value = Fraction(numerator, denominator)
- def __le__(self, other):
- if isinstance(other, MyFraction):
- return self.value <= other.value
- elif isinstance(other, (Fraction, int, float)):
- return self.value <= Fraction(other)
- else:
- return NotImplemented
- if __name__ == '__main__':
- f1 = MyFraction(1, 2)
- f2 = MyFraction(3, 4)
- print(f1 <= f2) # True
- print(f1 <= 0.5) # True
-
- # 4、日期比较
- from datetime import date
- class MyDate:
- def __init__(self, year, month, day):
- self.value = date(year, month, day)
- def __le__(self, other):
- if isinstance(other, MyDate):
- return self.value <= other.value
- elif isinstance(other, date):
- return self.value <= other
- else:
- return NotImplemented
- if __name__ == '__main__':
- d1 = MyDate(2024, 3, 15)
- d2 = MyDate(2024, 3, 17)
- print(d1 <= d2) # True
- print(d1 <= date(2024, 3, 15)) # True
-
- # 5、时间比较
- from datetime import time
- class MyTime:
- def __init__(self, hour, minute, second=0):
- self.value = time(hour, minute, second)
- def __le__(self, other):
- if isinstance(other, MyTime):
- return self.value <= other.value
- elif isinstance(other, time):
- return self.value <= other
- else:
- return NotImplemented
- if __name__ == '__main__':
- t1 = MyTime(10, 30)
- t2 = MyTime(11, 15)
- print(t1 <= t2) # True
- print(t1 <= time(10, 30)) # True
-
- # 6、价格比较
- class Price:
- def __init__(self, amount):
- self.amount = amount
- def __le__(self, other):
- if isinstance(other, Price):
- return self.amount <= other.amount
- elif isinstance(other, (int, float)):
- return self.amount <= other
- else:
- return NotImplemented
- if __name__ == '__main__':
- p1 = Price(10.99)
- p2 = Price(20.99)
- print(p1 <= p2) # True
- print(p2 <= 15.00) # False
-
- # 7、分数排名比较
- class StudentRank:
- def __init__(self, rank):
- self.rank = rank
- def __le__(self, other):
- if isinstance(other, StudentRank):
- return self.rank <= other.rank
- elif isinstance(other, int):
- return self.rank <= other
- else:
- return NotImplemented
- if __name__ == '__main__':
- r1 = StudentRank(1)
- r2 = StudentRank(5)
- print(r1 <= r2) # True
- print(r1 <= 3) # True
-
- # 8、版本比较
- import packaging.version
- class MyVersion:
- def __init__(self, version_str):
- self.value = packaging.version.parse(version_str)
- def __le__(self, other):
- if isinstance(other, MyVersion):
- return self.value <= other.value
- elif isinstance(other, str):
- return self.value <= packaging.version.parse(other)
- else:
- return NotImplemented
- if __name__ == '__main__':
- v1 = MyVersion("1.0.0")
- v2 = MyVersion("2.0.0")
- print(v1 <= v2) # True
- print(v1 <= "1.1.0") # True
43、__len__方法
43-1、语法
- __len__(self, /)
- Return len(self)
43-2、参数
43-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
43-2-2、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
43-3、功能
用于返回容器对象(如列表、元组、字典、字符串、集合以及用户定义的容器类)中元素的数量。
43-4、返回值
返回一个整数,表示对象的长度。
43-5、说明
如果没有返回整数或者引发异常,那么使用len()函数时会抛出异常。
43-6、用法
- # 043、__len__方法:
- # 1、简单的列表包装器
- class MyListWrapper:
- def __init__(self, lst):
- self.lst = lst
- def __len__(self):
- return len(self.lst)
-
- # 2、字符串长度计算
- class StringLength:
- def __init__(self, s):
- self.s = s
- def __len__(self):
- return len(self.s)
-
- # 3、文件行数计算
- class FileLineCounter:
- def __init__(self, file_path):
- self.file_path = file_path
- def __len__(self):
- with open(self.file_path, 'r') as file:
- return sum(1 for _ in file)
-
- # 4、自定义集合
- class MySet:
- def __init__(self, items):
- self.items = set(items)
- def __len__(self):
- return len(self.items)
-
- # 5、范围计数器
- class RangeCounter:
- def __init__(self, start, end):
- self.start = start
- self.end = end
- def __len__(self):
- return self.end - self.start
-
- # 6、图形顶点数
- class Graph:
- def __init__(self, vertices):
- self.vertices = vertices
- def __len__(self):
- return len(self.vertices)
-
- # 7、用户列表(考虑重复)
- class UserList:
- def __init__(self, users):
- self.users = list(set(users)) # 去重
- def __len__(self):
- return len(self.users)
-
- # 8、单词列表(从文本中提取)
- class WordList:
- def __init__(self, text):
- self.words = text.split()
- def __len__(self):
- return len(self.words)
-
- # 9、数据库记录数
- class DatabaseRecords:
- def __init__(self, db_connection):
- self.db_connection = db_connection
- def __len__(self):
- # 假设这里有一个方法可以从数据库中获取记录数
- return self.db_connection.get_record_count()
-
- # 10、自定义字典(仅计算键的数量)
- class MyDict:
- def __init__(self, **kwargs):
- self.data = kwargs
- def __len__(self):
- return len(self.data.keys())
-
- # 11、日期范围中的天数
- from datetime import date, timedelta
- class DateRange:
- def __init__(self, start_date, end_date):
- self.start_date = start_date
- self.end_date = end_date
- def __len__(self):
- return (self.end_date - self.start_date).days + 1
-
- # 12、自定义树形结构中的节点数
- class TreeNode:
- def __init__(self, value, children=None):
- self.value = value
- self.children = children if children is not None else []
- def __len__(self):
- count = 1
- for child in self.children:
- count += len(child)
- return count
评论记录:
回复评论: