当前位置:   article > 正文

Python魔法之旅-魔法方法(15)_python的魔法函数官方文档

python的魔法函数官方文档

目录

一、概述

1、定义

2、作用

二、应用场景

1、构造和析构

2、操作符重载

3、字符串和表示

4、容器管理

5、可调用对象

6、上下文管理

7、属性访问和描述符

8、迭代器和生成器

9、数值类型

10、复制和序列化

11、自定义元类行为

12、自定义类行为

13、类型检查和转换

14、自定义异常

三、学习方法

1、理解基础

2、查阅文档

3、编写示例

4、实践应用

5、阅读他人代码

6、参加社区讨论

7、持续学习

8、练习与总结

9、注意兼容性

10、避免过度使用

四、魔法方法

47、__mod__方法

47-1、语法

47-2、参数

47-3、功能

47-4、返回值

47-5、说明

47-6、用法

48、__mul__方法

48-1、语法

48-2、参数

48-3、功能

48-4、返回值

48-5、说明

48-6、用法

49、__ne__方法

49-1、语法

49-2、参数

49-3、功能

49-4、返回值

49-5、说明

49-6、用法

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

一、概述

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的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。

四、魔法方法

47、__mod__方法

47-1、语法
  1. __mod__(self, other, /)
  2. Return self % other
47-2、参数

47-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

47-2-2、other(必须)表示对self进行取模操作的另一个对象或值。

47-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

47-3、功能

        用于定义对象之间取模(求余数)的操作。

47-4、返回值

        返回一个值,该值表示self除以other的余数。

47-5、说明

        取模操作的规则是:

47-5-1、如果self和other都是整数,那么结果是self除以other的余数。

47-5-2、如果self和other是浮点数,那么结果也是浮点数,表示self除以other的余数。但是要注意,浮点数取模的行为在不同的系统和Python版本之间可能略有不同,因为浮点数的精度问题。

47-5-3、如果self或other是你自定义的类的实例,并且该类定义了 __mod__ 方法,那么Python将调用该方法来执行取模操作。

47-6、用法
  1. # 047、__mod__方法:
  2. # 1、自定义整数类
  3. class CustomInt:
  4. def __init__(self, value):
  5. self.value = int(value)
  6. def __mod__(self, other):
  7. if isinstance(other, CustomInt):
  8. other_value = other.value
  9. else:
  10. other_value = int(other)
  11. return CustomInt(self.value % other_value)
  12. def __str__(self):
  13. return str(self.value)
  14. if __name__ == '__main__':
  15. a = CustomInt(10)
  16. b = CustomInt(3)
  17. result = a % b
  18. print(str(result)) # 输出: 1
  19. # 2、颜色轮循环
  20. class ColorWheel:
  21. def __init__(self, colors):
  22. self.colors = colors
  23. self.current_index = 0
  24. def __mod__(self, n):
  25. return self.current_index % n
  26. def get_next_color(self):
  27. self.current_index = (self.current_index + 1) % len(self.colors)
  28. return self.colors[self.current_index]
  29. def set_color_index(self, index):
  30. self.current_index = index % len(self.colors)
  31. def __repr__(self):
  32. return f"ColorWheel(current_color={self.colors[self.current_index]})"
  33. if __name__ == '__main__':
  34. colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
  35. color_wheel = ColorWheel(colors)
  36. for _ in range(10):
  37. print(color_wheel.get_next_color())
  38. color_wheel.set_color_index(10)
  39. print(color_wheel) # 输出当前颜色轮的状态
  40. # 3、日期偏移
  41. from datetime import datetime, timedelta
  42. class CustomDate:
  43. def __init__(self, year, month, day):
  44. self.date = datetime(year, month, day)
  45. def __mod__(self, days):
  46. delta = timedelta(days=days)
  47. new_date = self.date + delta
  48. cycle_length = 7
  49. offset_within_cycle = (new_date.weekday() + 1) % cycle_length
  50. adjusted_date = new_date - timedelta(days=new_date.weekday()) + timedelta(days=offset_within_cycle)
  51. return CustomDate(adjusted_date.year, adjusted_date.month, adjusted_date.day)
  52. def __str__(self):
  53. return self.date.strftime("%Y-%m-%d")
  54. if __name__ == '__main__':
  55. date1 = CustomDate(2024, 6, 4)
  56. print(date1) # 输出:2024-06-04
  57. offset_date = date1 % 10
  58. print(offset_date) # 输出:2024-06-15

48、__mul__方法

48-1、语法
  1. __mul__(self, other, /)
  2. Return self * other
48-2、参数

48-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

48-2-2、 other(必须)表示与self相乘的另一个对象或值。

48-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

48-3、功能

        用于定义当对象使用*运算符进行乘法操作时的行为。

48-4、返回值

        返回一个值,该值表示self与other相乘的结果。

48-5、说明

        无

48-6、用法
  1. # 048、__mul__方法:
  2. # 1、矩阵乘法
  3. class Matrix:
  4. # 假设这是一个简单的2x2矩阵类
  5. def __init__(self, data):
  6. self.data = data
  7. def __mul__(self, other):
  8. if len(self.data) != len(other.data[0]):
  9. raise ValueError("矩阵维度不匹配!")
  10. result = [[0 for _ in range(len(other.data[0]))] for _ in range(len(self.data))]
  11. for i in range(len(self.data)):
  12. for j in range(len(other.data[0])):
  13. for k in range(len(other.data)):
  14. result[i][j] += self.data[i][k] * other.data[k][j]
  15. return Matrix(result)
  16. if __name__ == '__main__':
  17. A = Matrix([[3, 6], [5, 11]])
  18. B = Matrix([[10, 8], [10, 24]])
  19. C = A * B
  20. print(C.data) # 输出:[[90, 168], [160, 304]]
  21. # 2、复数乘法
  22. class ComplexNumber:
  23. def __init__(self, real, imag):
  24. self.real = real
  25. self.imag = imag
  26. def __mul__(self, other):
  27. real = self.real * other.real - self.imag * other.imag
  28. imag = self.real * other.imag + self.imag * other.real
  29. return ComplexNumber(real, imag)
  30. if __name__ == '__main__':
  31. c1 = ComplexNumber(5, 11)
  32. c2 = ComplexNumber(10, 24)
  33. c3 = c1 * c2
  34. print(c3.real, c3.imag) # 输出:-214 230
  35. # 3、向量点积
  36. class Vector:
  37. def __init__(self, data):
  38. self.data = data
  39. def __mul__(self, other):
  40. if len(self.data) != len(other.data):
  41. raise ValueError("向量维度不匹配!")
  42. result = sum(a * b for a, b in zip(self.data, other.data))
  43. return result
  44. if __name__ == '__main__':
  45. v1 = Vector([1, 2, 3])
  46. v2 = Vector([4, 5, 6])
  47. dot_product = v1 * v2
  48. print(dot_product) # 输出:32
  49. # 4、多项式乘法
  50. class Polynomial:
  51. def __init__(self, coeffs):
  52. self.coeffs = coeffs
  53. def __mul__(self, other):
  54. # 假设coeffs是降幂排列的系数列表
  55. result_coeffs = [0] * (len(self.coeffs) + len(other.coeffs) - 1)
  56. for i, a in enumerate(self.coeffs):
  57. for j, b in enumerate(other.coeffs):
  58. result_coeffs[i + j] += a * b
  59. # 删除结果中的前导零
  60. while result_coeffs and result_coeffs[-1] == 0:
  61. result_coeffs.pop()
  62. return Polynomial(result_coeffs)
  63. if __name__ == '__main__':
  64. p1 = Polynomial([1, 2, 3]) # 表示 3x^2 + 2x + 1
  65. p2 = Polynomial([4, 5]) # 表示 5x + 4
  66. p3 = p1 * p2
  67. print(p3.coeffs) # 输出:[4, 13, 22, 15]
  68. # 5、分数乘法
  69. from fractions import Fraction
  70. class RationalNumber:
  71. def __init__(self, numerator, denominator):
  72. self.numerator = numerator
  73. self.denominator = denominator
  74. self.simplify()
  75. def simplify(self):
  76. # 简化分数
  77. g = self.gcd(self.numerator, self.denominator)
  78. self.numerator //= g
  79. self.denominator //= g
  80. def gcd(self, a, b):
  81. while b:
  82. a, b = b, a % b
  83. return a
  84. def __mul__(self, other):
  85. return RationalNumber(
  86. self.numerator * other.numerator,
  87. self.denominator * other.denominator
  88. )
  89. def __str__(self):
  90. return f"{self.numerator}/{self.denominator}"
  91. if __name__ == '__main__':
  92. r1 = RationalNumber(1, 2)
  93. r2 = RationalNumber(3, 4)
  94. r3 = r1 * r2
  95. print(r3) # 输出: 3/8
  96. # 6、货币乘法(例如,计算总价)
  97. class Money:
  98. def __init__(self, amount, currency='USD'):
  99. self.amount = amount
  100. self.currency = currency
  101. def __mul__(self, other):
  102. if not isinstance(other, (int, float)):
  103. raise TypeError("Cannot multiply Money with non-numeric value.")
  104. return Money(self.amount * other, self.currency)
  105. def __str__(self):
  106. return f"{self.amount} {self.currency}"
  107. if __name__ == '__main__':
  108. m1 = Money(10, 'EUR')
  109. total = m1 * 2
  110. print(total) # 输出: 20 EUR
  111. # 7、向量与标量乘法
  112. class Vector:
  113. def __init__(self, *components):
  114. self.components = components
  115. def __mul__(self, scalar):
  116. if isinstance(scalar, (int, float)):
  117. return Vector(*[component * scalar for component in self.components])
  118. else:
  119. raise TypeError("Unsupported operand type for multiplication with Vector.")
  120. def __str__(self):
  121. return f"({', '.join(map(str, self.components))})"
  122. if __name__ == '__main__':
  123. v = Vector(1, 2, 3)
  124. s = 2
  125. scaled_v = v * s
  126. print(scaled_v) # 输出:(2, 4, 6)
  127. # 8、自定义四则运算类
  128. class CustomArithmetic:
  129. def __init__(self, value):
  130. self.value = value
  131. def __mul__(self, other):
  132. if isinstance(other, CustomArithmetic):
  133. return CustomArithmetic(self.value * other.value)
  134. elif isinstance(other, (int, float)):
  135. return CustomArithmetic(self.value * other)
  136. else:
  137. raise TypeError("Unsupported operand type for multiplication.")
  138. def __str__(self):
  139. return str(self.value)
  140. if __name__ == '__main__':
  141. a = CustomArithmetic(10)
  142. b = CustomArithmetic(24)
  143. c = a * b
  144. print(c) # 输出:240

49、__ne__方法

49-1、语法
  1. __ne__(self, other, /)
  2. Return self != other
49-2、参数

49-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

49-2-2、 other(必须)表示与self进行比较的另一个对象。

49-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

49-3、功能

        用于定义对象之间的“不等于”比较操作。

49-4、返回值

        返回一个布尔值:如果self和other不相等,则返回True;如果它们相等,则返回False。

49-5、说明

        无

49-6、用法
  1. # 049、__ne__方法:
  2. # 1、简单的数字类
  3. class Number:
  4. def __init__(self, value):
  5. self.value = value
  6. def __ne__(self, other):
  7. if isinstance(other, Number):
  8. return self.value != other.value
  9. return NotImplemented
  10. if __name__ == '__main__':
  11. n1 = Number(5)
  12. n2 = Number(5)
  13. print(n1 != n2) # 输出:False
  14. # 2、字符串包装类
  15. class StringWrapper:
  16. def __init__(self, string):
  17. self.string = string
  18. def __ne__(self, other):
  19. if isinstance(other, StringWrapper):
  20. return self.string != other.string
  21. return NotImplemented
  22. if __name__ == '__main__':
  23. s1 = StringWrapper("hello")
  24. s2 = StringWrapper("world")
  25. print(s1 != s2) # 输出:True
  26. # 3、坐标点类
  27. class Point:
  28. def __init__(self, x, y):
  29. self.x = x
  30. self.y = y
  31. def __ne__(self, other):
  32. if isinstance(other, Point):
  33. return self.x != other.x or self.y != other.y
  34. return NotImplemented
  35. if __name__ == '__main__':
  36. p1 = Point(1, 2)
  37. p2 = Point(1, 2)
  38. print(p1 != p2) # 输出:False
  39. # 4、用户名密码类(仅比较用户名)
  40. class Credentials:
  41. def __init__(self, username, password):
  42. self.username = username
  43. self.password = password
  44. def __ne__(self, other):
  45. if isinstance(other, Credentials):
  46. return self.username != other.username
  47. return NotImplemented
  48. if __name__ == '__main__':
  49. c1 = Credentials("user", "pass")
  50. c2 = Credentials("user", "otherpass")
  51. print(c1 != c2) # 输出:False,注意这里仅比较了用户名
  52. # 5、日期类
  53. from datetime import date
  54. class Date:
  55. def __init__(self, year, month, day):
  56. self.date = date(year, month, day)
  57. def __ne__(self, other):
  58. if isinstance(other, Date):
  59. return self.date != other.date
  60. return NotImplemented
  61. if __name__ == '__main__':
  62. d1 = Date(2024, 3, 15)
  63. d2 = Date(2024, 3, 16)
  64. print(d1 != d2) # 输出:True
  65. # 6、矩形类(比较面积)
  66. class Rectangle:
  67. def __init__(self, width, height):
  68. self.width = width
  69. self.height = height
  70. def area(self):
  71. return self.width * self.height
  72. def __ne__(self, other):
  73. if isinstance(other, Rectangle):
  74. return self.area() != other.area()
  75. return NotImplemented
  76. if __name__ == '__main__':
  77. r1 = Rectangle(3, 4)
  78. r2 = Rectangle(2, 6)
  79. print(r1 != r2) # 输出:False
  80. # 7、电子邮件地址类
  81. class EmailAddress:
  82. def __init__(self, address):
  83. self.address = address
  84. def __ne__(self, other):
  85. if isinstance(other, EmailAddress):
  86. return self.address.lower() != other.address.lower()
  87. return NotImplemented
  88. if __name__ == '__main__':
  89. e1 = EmailAddress("user@example.com")
  90. e2 = EmailAddress("User@Example.com") # 大小写不同
  91. print(e1 != e2) # 输出:False
  92. # 8、文件路径类(忽略大小写和路径分隔符)
  93. import os
  94. class FilePath:
  95. def __init__(self, path):
  96. self.path = os.path.normpath(path).lower()
  97. def __ne__(self, other):
  98. if isinstance(other, FilePath):
  99. return self.path != other.path
  100. return NotImplemented
  101. if __name__ == '__main__':
  102. p1 = FilePath("/home/user/documents/file.txt")
  103. p2 = FilePath("/home/USER/Documents/FILE.TXT") # 忽略大小写和路径分隔符
  104. print(p1 != p2) # 输出:False
  105. # 9、字典包装类(比较键和值)
  106. class DictWrapper:
  107. def __init__(self, dictionary):
  108. self.dictionary = dictionary
  109. def __ne__(self, other):
  110. if isinstance(other, DictWrapper):
  111. return self.dictionary != other.dictionary
  112. return NotImplemented
  113. if __name__ == '__main__':
  114. d1 = DictWrapper({"a": 1, "b": 2})
  115. d2 = DictWrapper({"a": 1, "b": 3})
  116. print(d1 != d2) # 输出:True
  117. # 10、集合包装类
  118. class SetWrapper:
  119. def __init__(self, set_items):
  120. self.set_items = set(set_items)
  121. def __ne__(self, other):
  122. if isinstance(other, SetWrapper):
  123. return self.set_items != other.set_items
  124. return NotImplemented
  125. if __name__ == '__main__':
  126. s1 = SetWrapper({1, 2, 3})
  127. s2 = SetWrapper({1, 2, 4})
  128. print(s1 != s2) # 输出:True

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/724541
推荐阅读
相关标签
  

闽ICP备14008679号