当前位置:   article > 正文

Python魔法之旅-魔法方法(15)

Python魔法之旅-魔法方法(15)

目录

一、概述

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/菜鸟追梦旅行/article/detail/690856
推荐阅读
相关标签
  

闽ICP备14008679号