当前位置:   article > 正文

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

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

目录

一、概述

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、避免过度使用

四、魔法方法

38、__ior__方法

38-1、语法

38-2、参数

38-3、功能

38-4、返回值

38-5、说明

38-6、用法

39、__isub__方法

39-1、语法

39-2、参数

39-3、功能

39-4、返回值

39-5、说明

39-6、用法

40、__iter__方法

40-1、语法

40-2、参数

40-3、功能

40-4、返回值

40-5、说明

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

四、魔法方法

38、__ior__方法

38-1、语法
  1. __ior__(self, other, /)
  2. Return self |= other
38-2、参数

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

38-2-2、 other(必须)表示要与self进行按位或操作的另一个对象,即__ior__ 法操作的右侧操作数。

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

38-3、功能

        用于定义对象的就地按位或(bitwise in-place OR)操作。

38-4、返回值

        返回self的引用(如果进行了就地修改)或一个新的对象(尽管不推荐)。

38-5、说明

        如果就地修改不可行或不合适,则可以选择返回一个新的对象,但这不是推荐的做法,因为它会违反 __ior__ 方法的预期语义。

38-6、用法
  1. # 038、__ior__方法:
  2. # 1、位运算类(BitSet)
  3. class BitSet:
  4. def __init__(self, value=0):
  5. self.value = value
  6. def __ior__(self, other):
  7. self.value |= other.value
  8. return self
  9. if __name__ == '__main__':
  10. b1 = BitSet(5) # 二进制 101
  11. b2 = BitSet(3) # 二进制 011
  12. b1 |= b2
  13. print(bin(b1.value)) # 输出:0b111
  14. # 2、集合就地合并
  15. class MySet(set):
  16. def __ior__(self, other):
  17. self.update(other)
  18. return self
  19. if __name__ == '__main__':
  20. s1 = MySet({1, 2, 3})
  21. s2 = {3, 4, 5}
  22. s1 |= s2
  23. print(s1) # 输出:MySet({1, 2, 3, 4, 5})
  24. # 3、自定义列表就地添加元素
  25. class MyList(list):
  26. def __ior__(self, other):
  27. if isinstance(other, list):
  28. self.extend(other)
  29. return self
  30. if __name__ == '__main__':
  31. l1 = MyList([1, 2, 3])
  32. l2 = [4, 5, 6]
  33. l1 |= l2
  34. print(l1) # 输出:[1, 2, 3, 4, 5, 6]
  35. # 4、自定义二进制字符串操作
  36. class BinaryString:
  37. def __init__(self, value):
  38. self.value = value
  39. def __ior__(self, other):
  40. if isinstance(other, BinaryString):
  41. self.value = bin(int(self.value, 2) | int(other.value, 2))[2:]
  42. return self
  43. def __str__(self):
  44. return self.value
  45. if __name__ == '__main__':
  46. b1 = BinaryString('1010')
  47. b2 = BinaryString('0110')
  48. b1 |= b2
  49. print(b1) # 输出:'1110'
  50. # 5、自定义整数范围类
  51. class IntRange:
  52. def __init__(self, start, end):
  53. self.start = min(start, end)
  54. self.end = max(start, end)
  55. def __ior__(self, other):
  56. if isinstance(other, IntRange):
  57. self.start = min(self.start, other.start)
  58. self.end = max(self.end, other.end)
  59. return self
  60. def __str__(self):
  61. return f'[{self.start}, {self.end}]'
  62. if __name__ == '__main__':
  63. r1 = IntRange(1, 5)
  64. r2 = IntRange(4, 10)
  65. r1 |= r2
  66. print(r1) # 输出:'[1, 10]'
  67. # 6、自定义权限类
  68. class Permission:
  69. READ = 1
  70. WRITE = 2
  71. EXECUTE = 4
  72. def __init__(self, value=0):
  73. self.value = value
  74. def __ior__(self, other):
  75. if isinstance(other, Permission):
  76. self.value |= other.value
  77. return self
  78. def __str__(self):
  79. perms = []
  80. if self.value & Permission.READ:
  81. perms.append('READ')
  82. if self.value & Permission.WRITE:
  83. perms.append('WRITE')
  84. if self.value & Permission.EXECUTE:
  85. perms.append('EXECUTE')
  86. return ', '.join(perms)
  87. if __name__ == '__main__':
  88. p1 = Permission(Permission.READ | Permission.WRITE)
  89. p2 = Permission(Permission.EXECUTE)
  90. p1 |= p2
  91. print(p1) # 输出:'READ, WRITE, EXECUTE'
  92. # 7、自定义图形颜色类
  93. class Color:
  94. RED = 1
  95. GREEN = 2
  96. BLUE = 4
  97. def __init__(self, value=0):
  98. self.value = value
  99. def __ior__(self, other):
  100. if isinstance(other, Color):
  101. self.value |= other.value
  102. return self
  103. def __str__(self):
  104. colors = []
  105. if self.value & Color.RED:
  106. colors.append('RED')
  107. if self.value & Color.GREEN:
  108. colors.append('GREEN')
  109. if self.value & Color.BLUE:
  110. colors.append('BLUE')
  111. return ', '.join(colors)
  112. if __name__ == '__main__':
  113. c1 = Color(Color.RED | Color.GREEN)
  114. c2 = Color(Color.BLUE)
  115. c1 |= c2
  116. print(c1) # 输出:'RED, GREEN, BLUE'
  117. # 8、自定义标签集合类
  118. class TagSet:
  119. def __init__(self, tags=None):
  120. self.tags = set(tags or [])
  121. def __ior__(self, other):
  122. if isinstance(other, TagSet):
  123. self.tags.update(other.tags)
  124. return self
  125. def __str__(self):
  126. return ', '.join(sorted(self.tags))
  127. if __name__ == '__main__':
  128. tags1 = TagSet(['python', 'data-science'])
  129. tags2 = TagSet(['data-science', 'machine-learning'])
  130. tags1 |= tags2
  131. print(tags1) # 输出:'data-science, machine-learning, python'
  132. # 9、自定义坐标范围类
  133. class CoordinateRange:
  134. def __init__(self, x_start, x_end, y_start, y_end):
  135. self.x_start = min(x_start, x_end)
  136. self.x_end = max(x_start, x_end)
  137. self.y_start = min(y_start, y_end)
  138. self.y_end = max(y_start, y_end)
  139. def __ior__(self, other):
  140. if isinstance(other, CoordinateRange):
  141. self.x_start = min(self.x_start, other.x_start)
  142. self.x_end = max(self.x_end, other.x_end)
  143. self.y_start = min(self.y_start, other.y_start)
  144. self.y_end = max(self.y_end, other.y_end)
  145. return self
  146. def __str__(self):
  147. return f'[{self.x_start}, {self.x_end}] x [{self.y_start}, {self.y_end}]'
  148. if __name__ == '__main__':
  149. range1 = CoordinateRange(1, 3, 2, 4)
  150. range2 = CoordinateRange(2, 5, 3, 6)
  151. range1 |= range2
  152. print(range1) # 输出:[1, 5] x [2, 6]
  153. # 10、自定义版本控制类
  154. class Version:
  155. def __init__(self, major=0, minor=0, patch=0):
  156. self.major = major
  157. self.minor = minor
  158. self.patch = patch
  159. def __ior__(self, other):
  160. if isinstance(other, Version):
  161. if other.major > self.major:
  162. self.major = other.major
  163. self.minor = other.minor
  164. self.patch = other.patch
  165. elif other.major == self.major and other.minor > self.minor:
  166. self.minor = other.minor
  167. self.patch = other.patch
  168. elif other.major == self.major and other.minor == self.minor and other.patch > self.patch:
  169. self.patch = other.patch
  170. return self
  171. def __str__(self):return f"{self.major}.{self.minor}.{self.patch}"
  172. if __name__ == '__main__':
  173. v1 = Version(1, 2, 3)
  174. v2 = Version(1, 3, 0)
  175. v1 |= v2
  176. print(v1) # 输出:1.3.0
  177. v3 = Version(2, 0, 0)
  178. v1 |= v3
  179. print(v1) # 输出:2.0.0
  180. # 11、自定义时间区间类
  181. from datetime import datetime, timedelta
  182. class TimeInterval:
  183. def __init__(self, start_time, end_time):
  184. self.start_time = start_time
  185. self.end_time = end_time
  186. def __ior__(self, other):
  187. if isinstance(other, TimeInterval):
  188. if self.end_time < other.start_time:
  189. # 两个区间不重叠,无需合并
  190. pass
  191. elif self.start_time > other.end_time:
  192. # 第一个区间在第二个之后,用第二个区间的起始时间更新第一个区间的起始时间
  193. self.start_time = other.start_time
  194. elif self.start_time <= other.start_time <= self.end_time:
  195. # 第二个区间的起始时间在第一个区间内,无需更新起始时间
  196. pass
  197. # 更新结束时间
  198. self.end_time = max(self.end_time, other.end_time)
  199. return self
  200. def __str__(self):
  201. return f"{self.start_time.strftime('%Y-%m-%d %H:%M:%S')} - {self.end_time.strftime('%Y-%m-%d %H:%M:%S')}"
  202. if __name__ == '__main__':
  203. start1 = datetime(2019, 3, 13, 8, 0, 0)
  204. end1 = datetime(2024, 6, 3, 11, 0, 0)
  205. start2 = datetime(2024, 3, 13, 8, 30, 0)
  206. end2 = datetime(2024, 6, 3, 11, 0, 0)
  207. interval1 = TimeInterval(start1, end1)
  208. interval2 = TimeInterval(start2, end2)
  209. interval1 |= interval2
  210. print(interval1) # 输出:2019-03-13 08:00:00 - 2024-06-03 11:00:00
  211. # 12、自定义图片编辑类
  212. class ImageEdit:
  213. def __init__(self):
  214. self.edits = {}
  215. def crop(self, x, y, width, height):
  216. # 假设我们存储编辑为字典形式,'crop' 是一个键,后面跟着参数
  217. self.edits['crop'] = (x, y, width, height)
  218. def rotate(self, degrees):
  219. self.edits['rotate'] = degrees
  220. # ... 可以添加其他编辑方法
  221. def __ior__(self, other):
  222. if isinstance(other, ImageEdit):
  223. # 合并另一个编辑对象的编辑效果
  224. self.edits.update(other.edits)
  225. return self
  226. def apply_edits(self, image):
  227. # 这里仅作为示例,不实现真正的图片编辑逻辑
  228. # 实际中,这里应该使用图像处理库(如PIL)来应用编辑效果
  229. print(f"Applying edits to image: {self.edits}")
  230. # 假设我们已经应用了编辑并返回了处理后的图片(这里仅返回原始图片作为示例)
  231. return image
  232. if __name__ == '__main__':
  233. edit1 = ImageEdit()
  234. edit1.crop(10, 10, 200, 200)
  235. edit1.rotate(45)
  236. edit2 = ImageEdit()
  237. edit2.rotate(90)
  238. # 合并编辑效果
  239. edit1 |= edit2
  240. # 假设我们有一个图片对象image
  241. image = "output.jpg"
  242. # 应用编辑效果(这里仅打印编辑信息)
  243. edited_image = edit1.apply_edits(image)
  244. print("Edits applied:", edit1.edits) # 输出:{'crop': (10, 10, 200, 200), 'rotate': 90}

39、__isub__方法

39-1、语法
  1. __isub__(self, other, /)
  2. Return self -= other
39-2、参数

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

39-2-2、 other(必须)表示与self 进行减法操作的对象,即__isub__方法操作的右侧操作数。

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

39-3、功能

        用于定义对象的就地减法赋值操作(in-place subtraction assignment)。

39-4、返回值

        返回 self 的引用(如果进行了就地修改)或一个新的对象(尽管不推荐)。

39-5、说明

        如果就地修改不可行或不合适,则可以选择返回一个新的对象,但这不是推荐的做法,因为它会违反 __isub__ 方法的预期语义。

39-6、用法
  1. # 039、__isub__方法:
  2. # 1、简单的整数类
  3. class Integer:
  4. def __init__(self, value):
  5. self.value = value
  6. def __isub__(self, other):
  7. if isinstance(other, int):
  8. self.value -= other
  9. return self
  10. else:
  11. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  12. type(self).__name__, type(other).__name__))
  13. def __repr__(self):
  14. return str(self.value)
  15. if __name__ == '__main__':
  16. a = Integer(10)
  17. b = 2
  18. a -= b
  19. print(a) # 输出: 8
  20. # 2、分数类
  21. from fractions import Fraction
  22. class MyFraction:
  23. def __init__(self, numerator, denominator=1):
  24. self.value = Fraction(numerator, denominator)
  25. def __isub__(self, other):
  26. if isinstance(other, (int, float, Fraction, MyFraction)):
  27. if isinstance(other, MyFraction):
  28. other = other.value
  29. self.value -= other
  30. return self
  31. else:
  32. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  33. type(self).__name__, type(other).__name__))
  34. def __repr__(self):
  35. return str(self.value)
  36. if __name__ == '__main__':
  37. f = MyFraction(1, 2)
  38. f -= MyFraction(1, 4)
  39. print(f) # 输出: 1/4
  40. # 3、复数类
  41. class ComplexNumber:
  42. def __init__(self, real, imag=0):
  43. self.real = real
  44. self.imag = imag
  45. def __isub__(self, other):
  46. if isinstance(other, (int, float, ComplexNumber)):
  47. if isinstance(other, ComplexNumber):
  48. other_real, other_imag = other.real, other.imag
  49. else:
  50. other_real, other_imag = other, 0
  51. self.real -= other_real
  52. self.imag -= other_imag
  53. return self
  54. else:
  55. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  56. type(self).__name__, type(other).__name__))
  57. def __repr__(self):
  58. return f"{self.real}+{self.imag}j"
  59. if __name__ == '__main__':
  60. c = ComplexNumber(1, 2)
  61. c -= 3
  62. print(c) # 输出: -2+2j
  63. # 4、点类(二维)
  64. class Point:
  65. def __init__(self, x, y):
  66. self.x = x
  67. self.y = y
  68. def __isub__(self, other):
  69. if isinstance(other, Point):
  70. self.x -= other.x
  71. self.y -= other.y
  72. return self
  73. else:
  74. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  75. type(self).__name__, type(other).__name__))
  76. def __repr__(self):
  77. return f"({self.x}, {self.y})"
  78. if __name__ == '__main__':
  79. p = Point(5, 3)
  80. p -= Point(1, 1)
  81. print(p) # 输出: (4, 2)
  82. # 5、列表减法(移除元素)
  83. class MyList:
  84. def __init__(self, items):
  85. self.items = list(items)
  86. def __isub__(self, other):
  87. if isinstance(other, (list, set, tuple)):
  88. for item in other:
  89. if item in self.items:
  90. self.items.remove(item)
  91. return self
  92. else:
  93. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  94. type(self).__name__, type(other).__name__))
  95. def __repr__(self):
  96. return str(self.items)
  97. if __name__ == '__main__':
  98. lst = MyList([1, 2, 3, 4, 5])
  99. lst -= [2, 4]
  100. print(lst) # 输出: [1, 3, 5]
  101. # 6、集合的差集
  102. class MySet(set):
  103. def __isub__(self, other):
  104. if isinstance(other, (set, frozenset)):
  105. super().__isub__(other)
  106. return self
  107. else:
  108. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  109. type(self).__name__, type(other).__name__))
  110. if __name__ == '__main__':
  111. s = MySet({1, 2, 3, 4, 5})
  112. s -= {2, 4}
  113. print(s) # 输出: MySet({1, 3, 5})
  114. # 7、自定义栈的弹出操作(模拟就地减法)
  115. class Stack:
  116. def __init__(self):
  117. self.items = []
  118. def push(self, item):
  119. self.items.append(item)
  120. def __isub__(self, count):
  121. if isinstance(count, int) and count > 0 and count <= len(self.items):
  122. self.items = self.items[:-count]
  123. return self
  124. else:
  125. raise ValueError("Count must be a positive integer not greater than stack size.")
  126. def __repr__(self):
  127. return str(self.items)
  128. if __name__ == '__main__':
  129. # 使用(这里的 `-=` 并不符合栈的标准操作,但仅为示例)
  130. stk = Stack()
  131. stk.push(1)
  132. stk.push(2)
  133. stk.push(3)
  134. stk -= 2 # 弹出顶部两个元素
  135. print(stk) # 输出: [1]
  136. # 8、矩阵类(二维列表)
  137. class Matrix:
  138. def __init__(self, matrix):
  139. self.matrix = [row[:] for row in matrix] # 浅拷贝,确保独立性
  140. def __isub__(self, other):
  141. if isinstance(other, Matrix) and len(self.matrix) == len(other.matrix) and all(
  142. len(row) == len(other_row) for row, other_row in zip(self.matrix, other.matrix)):
  143. for i in range(len(self.matrix)):
  144. for j in range(len(self.matrix[i])):
  145. self.matrix[i][j] -= other.matrix[i][j]
  146. return self
  147. else:
  148. raise ValueError("Matrix dimensions must agree")
  149. def __repr__(self):
  150. return str(self.matrix)
  151. if __name__ == '__main__':
  152. A = Matrix([[1, 2], [3, 4]])
  153. B = Matrix([[1, 1], [1, 1]])
  154. A -= B
  155. print(A) # 输出: [[0, 1], [2, 3]]
  156. # 9、计数器类(字典的变种)
  157. class Counter:
  158. def __init__(self, initial=None):
  159. self.counts = {}
  160. if initial is not None:
  161. for item, count in initial.items():
  162. self.counts[item] = count
  163. def __isub__(self, other):
  164. if isinstance(other, dict):
  165. for item, count in other.items():
  166. if item in self.counts:
  167. self.counts[item] -= count
  168. if self.counts[item] <= 0:
  169. del self.counts[item]
  170. return self
  171. else:
  172. raise TypeError("Unsupported operand type(s) for -=: '{}' and '{}'".format(
  173. type(self).__name__, type(other).__name__))
  174. def __repr__(self):
  175. return f"Counter({self.counts})"
  176. if __name__ == '__main__':
  177. c = Counter({'apple': 3, 'banana': 2})
  178. c -= {'apple': 1, 'orange': 1} # 注意:'orange' 初始不存在于计数器中
  179. print(c) # 应该输出: Counter({'apple': 2, 'banana': 2})
  180. # 10、自定义范围类(Range的变种)
  181. class CustomRange:
  182. def __init__(self, start, stop=None, step=1):
  183. if stop is None:
  184. start, stop = 0, start
  185. self.start = start
  186. self.stop = stop
  187. self.step = step
  188. def __isub__(self, other):
  189. if isinstance(other, int) and other >= 0:
  190. if self.step > 0:
  191. self.stop = max(self.start, self.stop - other)
  192. else:
  193. self.start = min(self.start, self.start + other)
  194. return self
  195. else:
  196. raise ValueError("Unsupported operand type or value for -= on CustomRange")
  197. def __iter__(self):
  198. current = self.start
  199. while self.step > 0 and current < self.stop or self.step < 0 and current > self.stop:
  200. yield current
  201. current += self.step
  202. def __repr__(self):
  203. return f"CustomRange({self.start}, {self.stop}, {self.step})"
  204. if __name__ == '__main__':
  205. rng = CustomRange(1, 10)
  206. for i in rng:
  207. print(i, end=' ') # 输出: 1 2 3 4 5 6 7 8 9
  208. print()
  209. rng -= 3
  210. for i in rng:
  211. print(i, end=' ') # 输出: 1 2 3 4 5 6

40、__iter__方法

40-1、语法
  1. __iter__(self, /)
  2. Implement iter(self)
40-2、参数

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

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

40-3、功能

        用于定义一个对象的迭代器。

40-4、返回值

        返回一个迭代器对象。

40-5、说明

        __iter__ 方法返回一个迭代器对象,该对象必须实现两个方法:__iter__ 和 __next__

40-5-1、__iter__ 方法:返回迭代器自身,这允许在迭代过程中,即使对象本身被用作迭代器,也可以保持迭代的一致性。

40-5-2、__next__ 方法:返回迭代器中的下一个元素,当没有更多元素可迭代时,它应该引发一个StopIteration异常。

40-6、用法
  1. # 040、__iter__方法:
  2. # 1、简单的列表迭代器
  3. class SimpleList:
  4. def __init__(self, data):
  5. self.data = data
  6. def __iter__(self):
  7. return iter(self.data)
  8. lst = SimpleList([3, 5, 6, 8, 10, 11, 24])
  9. for item in lst:
  10. print(item)
  11. # 3
  12. # 5
  13. # 6
  14. # 8
  15. # 10
  16. # 11
  17. # 24
  18. # 2、斐波那契数列迭代器
  19. class Fibonacci:
  20. def __init__(self, max_value):
  21. self.max_value = max_value
  22. self.a, self.b = 0, 1
  23. def __iter__(self):
  24. return self
  25. def __next__(self):
  26. if self.a > self.max_value:
  27. raise StopIteration
  28. fib = self.a
  29. self.a, self.b = self.b, self.a + self.b
  30. return fib
  31. fib = Fibonacci(100)
  32. for num in fib:
  33. print(num)
  34. # 0
  35. # 1
  36. # 1
  37. # 2
  38. # 3
  39. # 5
  40. # 8
  41. # 13
  42. # 21
  43. # 34
  44. # 55
  45. # 89
  46. # 3、文件逐行读取迭代器
  47. class LineIterator:
  48. def __init__(self, filename):
  49. self.file = open(filename, 'r')
  50. def __iter__(self):
  51. return self
  52. def __next__(self):
  53. line = self.file.readline()
  54. if not line:
  55. raise StopIteration
  56. return line.strip()
  57. def __del__(self):
  58. self.file.close()
  59. it = LineIterator('test.txt')
  60. for line in it:
  61. print(line)
  62. # 4、字符串迭代器(按字符)
  63. class StringIterator:
  64. def __init__(self, string):
  65. self.string = string
  66. self.index = 0
  67. def __iter__(self):
  68. return self
  69. def __next__(self):
  70. if self.index >= len(self.string):
  71. raise StopIteration
  72. char = self.string[self.index]
  73. self.index += 1
  74. return char
  75. str_it = StringIterator('hello')
  76. for char in str_it:
  77. print(char)
  78. # h
  79. # e
  80. # l
  81. # l
  82. # o
  83. # 5、字典迭代器(按键)
  84. class DictKeyIterator:
  85. def __init__(self, dictionary):
  86. self.dictionary = dictionary
  87. self.keys = iter(dictionary.keys())
  88. def __iter__(self):
  89. return self
  90. def __next__(self):
  91. return next(self.keys)
  92. d = {'a': 1, 'b': 2, 'c': 3}
  93. it = DictKeyIterator(d)
  94. for key in it:
  95. print(key)
  96. # a
  97. # b
  98. # c
  99. # 6、自定义集合迭代器(按特定顺序,如降序)
  100. class SortedSetIterator:
  101. def __init__(self, set_data):
  102. self.set_data = sorted(set_data, reverse=True)
  103. self.index = 0
  104. def __iter__(self):
  105. return self
  106. def __next__(self):
  107. if self.index >= len(self.set_data):
  108. raise StopIteration
  109. item = self.set_data[self.index]
  110. self.index += 1
  111. return item
  112. s = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}
  113. it = SortedSetIterator(s)
  114. for item in it:
  115. print(item)
  116. # 9
  117. # 6
  118. # 5
  119. # 4
  120. # 3
  121. # 2
  122. # 1

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

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

闽ICP备14008679号