赞
踩
目录
魔法方法(Magic Methods/Special Methods,也称特殊方法或双下划线方法)是Python中一类具有特殊命名规则的方法,它们的名称通常以双下划线(`__`)开头和结尾。
魔法方法用于在特定情况下自动被Python解释器调用,而不需要显式地调用它们,它们提供了一种机制,让你可以定义自定义类时具有与内置类型相似的行为。
魔法方法允许开发者重载Python中的一些内置操作或函数的行为,从而为自定义的类添加特殊的功能。
1-1、__init__(self, [args...]):在创建对象时初始化属性。
1-2、__new__(cls, [args...]):在创建对象时控制实例的创建过程(通常与元类一起使用)。
1-3、__del__(self):在对象被销毁前执行清理操作,如关闭文件或释放资源。
2-1、__add__(self, other)、__sub__(self, other)、__mul__(self, other)等:自定义对象之间的算术运算。
2-2、__eq__(self, other)、__ne__(self, other)、__lt__(self, other)等:定义对象之间的比较操作。
3-1、__str__(self):定义对象的字符串表示,常用于print()函数。
3-2、__repr__(self):定义对象的官方字符串表示,用于repr()函数和交互式解释器。
4-1、__getitem__(self, key)、__setitem__(self, key, value)、__delitem__(self, key):用于实现类似列表或字典的索引访问、设置和删除操作。
4-2、__len__(self):返回对象的长度或元素个数。
5-1、__call__(self, [args...]):允许对象像函数一样被调用。
6-1、__enter__(self)、__exit__(self, exc_type, exc_val, exc_tb):用于实现上下文管理器,如with语句中的对象。
7-1、__getattr__, __setattr__, __delattr__:这些方法允许对象在访问或修改不存在的属性时执行自定义操作。
7-2、描述符(Descriptors)是实现了__get__, __set__, 和__delete__方法的对象,它们可以控制对另一个对象属性的访问。
8-1、__iter__和__next__:这些方法允许对象支持迭代操作,如使用for循环遍历对象。
8-2、__aiter__, __anext__:这些是异步迭代器的魔法方法,用于支持异步迭代。
9-1、__int__(self)、__float__(self)、__complex__(self):定义对象到数值类型的转换。
9-2、__index__(self):定义对象用于切片时的整数转换。
10-1、__copy__和__deepcopy__:允许对象支持浅复制和深复制操作。
10-2、__getstate__和__setstate__:用于自定义对象的序列化和反序列化过程。
11-1、__metaclass__(Python 2)或元类本身(Python 3):允许自定义类的创建过程,如动态创建类、修改类的定义等。
12-1、__init__和__new__:用于初始化对象或控制对象的创建过程。
12-2、__init_subclass__:在子类被创建时调用,允许在子类中执行一些额外的操作。
13-1、__instancecheck__和__subclasscheck__:用于自定义isinstance()和issubclass()函数的行为。
14-1、你可以通过继承内置的Exception类来创建自定义的异常类,并定义其特定的行为。
要学好Python的魔法方法,你可以遵循以下方法及步骤:
首先确保你对Python的基本语法、数据类型、类和对象等概念有深入的理解,这些是理解魔法方法的基础。
仔细阅读Python官方文档中关于魔法方法的部分,文档会详细解释每个魔法方法的作用、参数和返回值。你可以通过访问Python的官方网站或使用help()函数在Python解释器中查看文档。
为每个魔法方法编写简单的示例代码,以便更好地理解其用法和效果,通过实际编写和运行代码,你可以更直观地感受到魔法方法如何改变对象的行为。
在实际项目中尝试使用魔法方法。如,你可以创建一个自定义的集合类,使用__getitem__、__setitem__和__delitem__方法来实现索引操作。只有通过实践应用,你才能更深入地理解魔法方法的用途和重要性。
阅读开源项目或他人编写的代码,特别是那些使用了魔法方法的代码,这可以帮助你学习如何在实际项目中使用魔法方法。通过分析他人代码中的魔法方法使用方式,你可以学习到一些新的技巧和最佳实践。
参与Python社区的讨论,与其他开发者交流关于魔法方法的使用经验和技巧,在社区中提问或回答关于魔法方法的问题,这可以帮助你更深入地理解魔法方法并发现新的应用场景。
Python语言和其生态系统不断发展,新的魔法方法和功能可能会不断被引入,保持对Python社区的关注,及时学习新的魔法方法和最佳实践。
多做练习,通过编写各种使用魔法方法的代码来巩固你的理解,定期总结你学到的知识和经验,形成自己的知识体系。
在使用魔法方法时,要注意不同Python版本之间的兼容性差异,确保你的代码在不同版本的Python中都能正常工作。
虽然魔法方法非常强大,但过度使用可能会导致代码难以理解和维护,在编写代码时,要权衡使用魔法方法的利弊,避免滥用。
总之,学好Python的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。
- __mod__(self, other, /)
- Return self % other
47-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
47-2-2、other(必须):表示对self进行取模操作的另一个对象或值。
47-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
用于定义对象之间取模(求余数)的操作。
返回一个值,该值表示self除以other的余数。
取模操作的规则是:
47-5-1、如果self和other都是整数,那么结果是self除以other的余数。
47-5-2、如果self和other是浮点数,那么结果也是浮点数,表示self除以other的余数。但是要注意,浮点数取模的行为在不同的系统和Python版本之间可能略有不同,因为浮点数的精度问题。
47-5-3、如果self或other是你自定义的类的实例,并且该类定义了 __mod
__
方法,那么Python将调用该方法来执行取模操作。
- # 047、__mod__方法:
- # 1、自定义整数类
- class CustomInt:
- def __init__(self, value):
- self.value = int(value)
- def __mod__(self, other):
- if isinstance(other, CustomInt):
- other_value = other.value
- else:
- other_value = int(other)
- return CustomInt(self.value % other_value)
- def __str__(self):
- return str(self.value)
- if __name__ == '__main__':
- a = CustomInt(10)
- b = CustomInt(3)
- result = a % b
- print(str(result)) # 输出: 1
-
- # 2、颜色轮循环
- class ColorWheel:
- def __init__(self, colors):
- self.colors = colors
- self.current_index = 0
- def __mod__(self, n):
- return self.current_index % n
- def get_next_color(self):
- self.current_index = (self.current_index + 1) % len(self.colors)
- return self.colors[self.current_index]
- def set_color_index(self, index):
- self.current_index = index % len(self.colors)
- def __repr__(self):
- return f"ColorWheel(current_color={self.colors[self.current_index]})"
- if __name__ == '__main__':
- colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
- color_wheel = ColorWheel(colors)
- for _ in range(10):
- print(color_wheel.get_next_color())
- color_wheel.set_color_index(10)
- print(color_wheel) # 输出当前颜色轮的状态
-
- # 3、日期偏移
- from datetime import datetime, timedelta
- class CustomDate:
- def __init__(self, year, month, day):
- self.date = datetime(year, month, day)
- def __mod__(self, days):
- delta = timedelta(days=days)
- new_date = self.date + delta
- cycle_length = 7
- offset_within_cycle = (new_date.weekday() + 1) % cycle_length
- adjusted_date = new_date - timedelta(days=new_date.weekday()) + timedelta(days=offset_within_cycle)
- return CustomDate(adjusted_date.year, adjusted_date.month, adjusted_date.day)
- def __str__(self):
- return self.date.strftime("%Y-%m-%d")
- if __name__ == '__main__':
- date1 = CustomDate(2024, 6, 4)
- print(date1) # 输出:2024-06-04
- offset_date = date1 % 10
- print(offset_date) # 输出:2024-06-15
- __mul__(self, other, /)
- Return self * other
48-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
48-2-2、 other(必须):表示与self相乘的另一个对象或值。
48-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
用于定义当对象使用*运算符进行乘法操作时的行为。
返回一个值,该值表示self与other相乘的结果。
无
- # 048、__mul__方法:
- # 1、矩阵乘法
- class Matrix:
- # 假设这是一个简单的2x2矩阵类
- def __init__(self, data):
- self.data = data
- def __mul__(self, other):
- if len(self.data) != len(other.data[0]):
- raise ValueError("矩阵维度不匹配!")
- result = [[0 for _ in range(len(other.data[0]))] for _ in range(len(self.data))]
- for i in range(len(self.data)):
- for j in range(len(other.data[0])):
- for k in range(len(other.data)):
- result[i][j] += self.data[i][k] * other.data[k][j]
- return Matrix(result)
- if __name__ == '__main__':
- A = Matrix([[3, 6], [5, 11]])
- B = Matrix([[10, 8], [10, 24]])
- C = A * B
- print(C.data) # 输出:[[90, 168], [160, 304]]
-
- # 2、复数乘法
- class ComplexNumber:
- def __init__(self, real, imag):
- self.real = real
- self.imag = imag
- def __mul__(self, other):
- real = self.real * other.real - self.imag * other.imag
- imag = self.real * other.imag + self.imag * other.real
- return ComplexNumber(real, imag)
- if __name__ == '__main__':
- c1 = ComplexNumber(5, 11)
- c2 = ComplexNumber(10, 24)
- c3 = c1 * c2
- print(c3.real, c3.imag) # 输出:-214 230
-
- # 3、向量点积
- class Vector:
- def __init__(self, data):
- self.data = data
- def __mul__(self, other):
- if len(self.data) != len(other.data):
- raise ValueError("向量维度不匹配!")
- result = sum(a * b for a, b in zip(self.data, other.data))
- return result
- if __name__ == '__main__':
- v1 = Vector([1, 2, 3])
- v2 = Vector([4, 5, 6])
- dot_product = v1 * v2
- print(dot_product) # 输出:32
-
- # 4、多项式乘法
- class Polynomial:
- def __init__(self, coeffs):
- self.coeffs = coeffs
- def __mul__(self, other):
- # 假设coeffs是降幂排列的系数列表
- result_coeffs = [0] * (len(self.coeffs) + len(other.coeffs) - 1)
- for i, a in enumerate(self.coeffs):
- for j, b in enumerate(other.coeffs):
- result_coeffs[i + j] += a * b
- # 删除结果中的前导零
- while result_coeffs and result_coeffs[-1] == 0:
- result_coeffs.pop()
- return Polynomial(result_coeffs)
- if __name__ == '__main__':
- p1 = Polynomial([1, 2, 3]) # 表示 3x^2 + 2x + 1
- p2 = Polynomial([4, 5]) # 表示 5x + 4
- p3 = p1 * p2
- print(p3.coeffs) # 输出:[4, 13, 22, 15]
-
- # 5、分数乘法
- from fractions import Fraction
- class RationalNumber:
- def __init__(self, numerator, denominator):
- self.numerator = numerator
- self.denominator = denominator
- self.simplify()
- def simplify(self):
- # 简化分数
- g = self.gcd(self.numerator, self.denominator)
- self.numerator //= g
- self.denominator //= g
- def gcd(self, a, b):
- while b:
- a, b = b, a % b
- return a
- def __mul__(self, other):
- return RationalNumber(
- self.numerator * other.numerator,
- self.denominator * other.denominator
- )
- def __str__(self):
- return f"{self.numerator}/{self.denominator}"
- if __name__ == '__main__':
- r1 = RationalNumber(1, 2)
- r2 = RationalNumber(3, 4)
- r3 = r1 * r2
- print(r3) # 输出: 3/8
-
- # 6、货币乘法(例如,计算总价)
- class Money:
- def __init__(self, amount, currency='USD'):
- self.amount = amount
- self.currency = currency
- def __mul__(self, other):
- if not isinstance(other, (int, float)):
- raise TypeError("Cannot multiply Money with non-numeric value.")
- return Money(self.amount * other, self.currency)
- def __str__(self):
- return f"{self.amount} {self.currency}"
- if __name__ == '__main__':
- m1 = Money(10, 'EUR')
- total = m1 * 2
- print(total) # 输出: 20 EUR
-
- # 7、向量与标量乘法
- class Vector:
- def __init__(self, *components):
- self.components = components
- def __mul__(self, scalar):
- if isinstance(scalar, (int, float)):
- return Vector(*[component * scalar for component in self.components])
- else:
- raise TypeError("Unsupported operand type for multiplication with Vector.")
- def __str__(self):
- return f"({', '.join(map(str, self.components))})"
- if __name__ == '__main__':
- v = Vector(1, 2, 3)
- s = 2
- scaled_v = v * s
- print(scaled_v) # 输出:(2, 4, 6)
-
- # 8、自定义四则运算类
- class CustomArithmetic:
- def __init__(self, value):
- self.value = value
- def __mul__(self, other):
- if isinstance(other, CustomArithmetic):
- return CustomArithmetic(self.value * other.value)
- elif isinstance(other, (int, float)):
- return CustomArithmetic(self.value * other)
- else:
- raise TypeError("Unsupported operand type for multiplication.")
- def __str__(self):
- return str(self.value)
- if __name__ == '__main__':
- a = CustomArithmetic(10)
- b = CustomArithmetic(24)
- c = a * b
- print(c) # 输出:240
- __ne__(self, other, /)
- Return self != other
49-2-1、self(必须):一个对实例对象本身的引用,在类的所有方法中都会自动传递。
49-2-2、 other(必须):表示与self进行比较的另一个对象。
49-2-3、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。
用于定义对象之间的“不等于”比较操作。
返回一个布尔值:如果self和other不相等,则返回True;如果它们相等,则返回False。
无
- # 049、__ne__方法:
- # 1、简单的数字类
- class Number:
- def __init__(self, value):
- self.value = value
- def __ne__(self, other):
- if isinstance(other, Number):
- return self.value != other.value
- return NotImplemented
- if __name__ == '__main__':
- n1 = Number(5)
- n2 = Number(5)
- print(n1 != n2) # 输出:False
-
- # 2、字符串包装类
- class StringWrapper:
- def __init__(self, string):
- self.string = string
- def __ne__(self, other):
- if isinstance(other, StringWrapper):
- return self.string != other.string
- return NotImplemented
- if __name__ == '__main__':
- s1 = StringWrapper("hello")
- s2 = StringWrapper("world")
- print(s1 != s2) # 输出:True
-
- # 3、坐标点类
- class Point:
- def __init__(self, x, y):
- self.x = x
- self.y = y
- def __ne__(self, other):
- if isinstance(other, Point):
- return self.x != other.x or self.y != other.y
- return NotImplemented
- if __name__ == '__main__':
- p1 = Point(1, 2)
- p2 = Point(1, 2)
- print(p1 != p2) # 输出:False
-
- # 4、用户名密码类(仅比较用户名)
- class Credentials:
- def __init__(self, username, password):
- self.username = username
- self.password = password
- def __ne__(self, other):
- if isinstance(other, Credentials):
- return self.username != other.username
- return NotImplemented
- if __name__ == '__main__':
- c1 = Credentials("user", "pass")
- c2 = Credentials("user", "otherpass")
- print(c1 != c2) # 输出:False,注意这里仅比较了用户名
-
- # 5、日期类
- from datetime import date
- class Date:
- def __init__(self, year, month, day):
- self.date = date(year, month, day)
- def __ne__(self, other):
- if isinstance(other, Date):
- return self.date != other.date
- return NotImplemented
- if __name__ == '__main__':
- d1 = Date(2024, 3, 15)
- d2 = Date(2024, 3, 16)
- print(d1 != d2) # 输出:True
-
- # 6、矩形类(比较面积)
- class Rectangle:
- def __init__(self, width, height):
- self.width = width
- self.height = height
- def area(self):
- return self.width * self.height
- def __ne__(self, other):
- if isinstance(other, Rectangle):
- return self.area() != other.area()
- return NotImplemented
- if __name__ == '__main__':
- r1 = Rectangle(3, 4)
- r2 = Rectangle(2, 6)
- print(r1 != r2) # 输出:False
-
- # 7、电子邮件地址类
- class EmailAddress:
- def __init__(self, address):
- self.address = address
- def __ne__(self, other):
- if isinstance(other, EmailAddress):
- return self.address.lower() != other.address.lower()
- return NotImplemented
- if __name__ == '__main__':
- e1 = EmailAddress("user@example.com")
- e2 = EmailAddress("User@Example.com") # 大小写不同
- print(e1 != e2) # 输出:False
-
- # 8、文件路径类(忽略大小写和路径分隔符)
- import os
- class FilePath:
- def __init__(self, path):
- self.path = os.path.normpath(path).lower()
- def __ne__(self, other):
- if isinstance(other, FilePath):
- return self.path != other.path
- return NotImplemented
- if __name__ == '__main__':
- p1 = FilePath("/home/user/documents/file.txt")
- p2 = FilePath("/home/USER/Documents/FILE.TXT") # 忽略大小写和路径分隔符
- print(p1 != p2) # 输出:False
-
- # 9、字典包装类(比较键和值)
- class DictWrapper:
- def __init__(self, dictionary):
- self.dictionary = dictionary
- def __ne__(self, other):
- if isinstance(other, DictWrapper):
- return self.dictionary != other.dictionary
- return NotImplemented
- if __name__ == '__main__':
- d1 = DictWrapper({"a": 1, "b": 2})
- d2 = DictWrapper({"a": 1, "b": 3})
- print(d1 != d2) # 输出:True
-
- # 10、集合包装类
- class SetWrapper:
- def __init__(self, set_items):
- self.set_items = set(set_items)
- def __ne__(self, other):
- if isinstance(other, SetWrapper):
- return self.set_items != other.set_items
- return NotImplemented
- if __name__ == '__main__':
- s1 = SetWrapper({1, 2, 3})
- s2 = SetWrapper({1, 2, 4})
- print(s1 != s2) # 输出:True
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。