首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 25-03-03 05:08
  • 3353
  • 9355
blog.csdn.net

目录

一、概述

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、博客个人主页

遨游码海,我心飞扬
微信名片
注:本文转载自blog.csdn.net的神奇夜光杯的文章"https://myelsa1024.blog.csdn.net/article/details/139388485"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top