首页 最新 热门 推荐

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

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

  • 25-03-03 05:08
  • 2175
  • 7056
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、避免过度使用

四、魔法方法

44、__length_hint__方法

44-1、语法

44-2、参数

44-3、功能

44-4、返回值

44-5、说明

44-6、用法

45、__lshift__方法

45-1、语法

45-2、参数

45-3、功能

45-4、返回值

45-5、说明

45-6、用法

46、__lt__方法

46-1、语法

46-2、参数

46-3、功能

46-4、返回值

46-5、说明

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

四、魔法方法

44、__length_hint__方法

44-1、语法
  1. __length_hint__(self, /)
  2. Private method returning an estimate of len(list(it))
44-2、参数

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

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

44-3、功能

        为那些需要知道迭代器大致长度的函数或方法提供一个长度提示。

44-4、返回值

        返回一个整数或None。

44-5、说明

   __length_hint__方法应该返回一个整数或None:

44-5-1、如果返回整数,它应该是一个对迭代器长度的合理估计,这个估计可能并不总是准确的,但它应该尽可能接近实际长度。

44-5-2、如果迭代器长度未知或无法合理估计,则应返回None。

44-6、用法
  1. # 044、__length_hint__方法:
  2. # 1、简单的列表包装器
  3. class MyListWrapper:
  4. def __init__(self, lst):
  5. self.lst = lst
  6. def __length_hint__(self):
  7. return len(self.lst)
  8. # 2、迭代器长度提示
  9. class MyIterator:
  10. def __init__(self, numbers):
  11. self.numbers = numbers
  12. self.index = 0
  13. def __iter__(self):
  14. return self
  15. def __next__(self):
  16. if self.index < len(self.numbers):
  17. result = self.numbers[self.index]
  18. self.index += 1
  19. return result
  20. raise StopIteration
  21. def __length_hint__(self):
  22. return len(self.numbers) - self.index
  23. # 3、动态生成的序列
  24. class DynamicSequence:
  25. def __init__(self, start, end):
  26. self.start = start
  27. self.end = end
  28. def __iter__(self):
  29. return self
  30. def __next__(self):
  31. if self.start > self.end:
  32. raise StopIteration
  33. current = self.start
  34. self.start += 1
  35. return current
  36. def __length_hint__(self):
  37. return self.end - self.start + 1 if self.start <= self.end else 0
  38. # 4、缓存长度的迭代器
  39. class CachedLengthIterator:
  40. def __init__(self, iterable):
  41. self.iterable = iterable
  42. self._length = None
  43. def __iter__(self):
  44. return iter(self.iterable)
  45. def __length_hint__(self):
  46. if self._length is None:
  47. self._length = sum(1 for _ in self.iterable)
  48. return self._length
  49. # 5、生成器长度提示(通常不准确,因为生成器是动态的)
  50. def my_generator(n):
  51. for i in range(n):
  52. yield i
  53. class GeneratorWrapper:
  54. def __init__(self, generator_func, *args, **kwargs):
  55. self.generator = generator_func(*args, **kwargs)
  56. self._hint = None
  57. def __iter__(self):
  58. return iter(self.generator)
  59. def __length_hint__(self):
  60. if self._hint is None:
  61. # 注意:这只是一个示例,对于真正的生成器可能不准确
  62. self._hint = sum(1 for _ in self.generator)
  63. return self._hint
  64. # 使用示例:GeneratorWrapper(my_generator, 10)
  65. # 6、模拟数据库查询结果
  66. class DatabaseQueryResult:
  67. def __init__(self, count):
  68. self.count = count
  69. def __length_hint__(self):
  70. return self.count
  71. # 7、文件行数预估(基于文件大小)
  72. class FileLineCounterApprox:
  73. def __init__(self, file_path, avg_line_length=100): # 假设平均行长为100字节
  74. self.file_path = file_path
  75. self.avg_line_length = avg_line_length
  76. def __length_hint__(self):
  77. with open(self.file_path, 'rb') as file:
  78. return file.seek(0, 2) // self.avg_line_length # 粗略估计
  79. # 8、树形结构节点数预估
  80. class TreeNode:
  81. def __init__(self, value, children=None):
  82. self.value = value
  83. self.children = children if children is not None else []
  84. def __length_hint__(self):
  85. # 假设这是一个完全二叉树,用于示例
  86. return (2 ** self.depth()) - 1 if self.is_full_binary_tree() else "unknown"
  87. def depth(self):
  88. # 需要实现一个计算树深度的函数
  89. pass
  90. def is_full_binary_tree(self):
  91. # 需要实现一个检查树是否是完全二叉树的函数
  92. pass
  93. # 注意:在实际应用中,树的长度(即节点数)可能需要递归遍历才能准确计算
  94. # 9、网络请求结果集大小预估
  95. class APIResult:
  96. def __init__(self, response_headers):
  97. self.response_headers = response_headers
  98. def __length_hint__(self):
  99. # 假设API响应头中包含了一个关于结果集大小的字段
  100. content_length = self.response_headers.get('X-Result-Set-Size', None)
  101. return int(content_length) if content_length is not None and content_length.isdigit() else "unknown"
  102. # 注意:这个预估是基于假设的HTTP头字段,实际API可能不会有这样的字段
  103. # 10、流式数据处理长度提示
  104. class StreamProcessor:
  105. def __init__(self, stream):
  106. self.stream = stream
  107. self._processed_count = 0
  108. def process(self, chunk_size=1024):
  109. # 处理流数据,这里只是模拟
  110. for _ in range(chunk_size):
  111. # 假设每次处理一个数据单元
  112. self._processed_count += 1
  113. def __length_hint__(self):
  114. # 流数据长度通常未知,但可以提供已处理的数量
  115. return self._processed_count
  116. # 注意:流数据的长度通常是未知的,除非有额外的信息或上下文
  117. # 11、自定义集合大小预估
  118. class CustomSet:
  119. def __init__(self, iterable=()):
  120. self._set = set(iterable)
  121. self._hint = None
  122. def add(self, item):
  123. self._set.add(item)
  124. self._hint = None # 清除长度提示缓存
  125. def remove(self, item):
  126. self._set.remove(item)
  127. self._hint = None
  128. def __iter__(self):
  129. return iter(self._set)
  130. def __len__(self):
  131. return len(self._set)
  132. def __length_hint__(self):
  133. if self._hint is None:
  134. self._hint = len(self) # 只有在需要时才计算长度
  135. return self._hint
  136. # 注意:在实际应用中,集合的大小可以直接通过len()函数获取,但这里展示了如何使用__length_hint__进行缓存

45、__lshift__方法

45-1、语法
  1. __lshift__(self, other, /)
  2. Return self << other
45-2、参数

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

45-2-2、 other(必须):表示与self进行左移操作的另一个对象或整数。

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

45-3、功能

        用于定义对象与左移位运算符<<的行为。

45-4、返回值

        返回一个与self类型相同或兼容的对象,该对象表示self对象左移other位之后的结果。

45-5、说明

        如果类没有定义__lshift__方法,并且尝试使用左移位运算符<<对其实例进行操作,将会引发一个TypeError。

45-6、用法
  1. # 045、__lshift__方法:
  2. # 1、二进制位移
  3. class BinaryShift:
  4. def __init__(self, value):
  5. self.value = value
  6. def __lshift__(self, other):
  7. return BinaryShift(self.value << other)
  8. if __name__ == '__main__':
  9. a = BinaryShift(4)
  10. b = a << 2 # 相当于 4 << 2 = 16
  11. print(b.value) # 输出 16
  12. # 2、整数列表左移
  13. class IntList:
  14. def __init__(self, values):
  15. self.values = values
  16. def __lshift__(self, other):
  17. if other < 0 or other >= len(self.values):
  18. raise ValueError("Invalid shift amount")
  19. return IntList(self.values[other:] + self.values[:other])
  20. if __name__ == '__main__':
  21. lst = IntList([3, 5, 6, 8, 10, 11, 24])
  22. shifted = lst << 2 # 相当于 [6, 8, 10, 11, 24, 3, 5]
  23. print(shifted.values) # 输出 [6, 8, 10, 11, 24, 3, 5]
  24. # 3、字符串左移
  25. class StringShift:
  26. def __init__(self, value):
  27. self.value = value
  28. def __lshift__(self, other):
  29. if other < 0:
  30. return StringShift(self.value[-other:] + self.value[:-other])
  31. elif other >= len(self.value):
  32. return StringShift(self.value)
  33. else:
  34. return StringShift(self.value[other:] + self.value[:other])
  35. if __name__ == '__main__':
  36. s = StringShift("hello")
  37. shifted = s << 2 # 相当于 "llohe"
  38. print(shifted.value) # 输出 "llohe"
  39. # 4、时间戳左移(模拟时间偏移)
  40. from datetime import datetime, timedelta
  41. class TimestampShift:
  42. def __init__(self, timestamp):
  43. self.timestamp = timestamp
  44. def __lshift__(self, other):
  45. # 假设 other 是天数
  46. return TimestampShift(self.timestamp + timedelta(days=other))
  47. if __name__ == '__main__':
  48. now = datetime.now()
  49. ts = TimestampShift(now)
  50. future = ts << 10 # 10天后的时间
  51. print(future.timestamp) # 输出10天后的日期时间
  52. # 5、图形对象的水平移动
  53. class Shape:
  54. def __init__(self, x, y):
  55. self.x = x
  56. self.y = y
  57. def __lshift__(self, other):
  58. return Shape(self.x + other, self.y)
  59. if __name__ == '__main__':
  60. rect = Shape(10, 24)
  61. moved = rect << 5 # 向右移动5个单位
  62. print(moved.x, moved.y) # 输出 15 24
  63. # 6、权重调整(模拟权重左移)
  64. class WeightedItem:
  65. def __init__(self, value, weight):
  66. self.value = value
  67. self.weight = weight
  68. def __lshift__(self, other):
  69. # 假设 other 是权重增加的因子(例如,左移1位相当于权重乘以2)
  70. return WeightedItem(self.value, self.weight * (2 ** other))
  71. if __name__ == '__main__':
  72. item = WeightedItem('apple', 1)
  73. item_with_higher_weight = item << 1 # 权重变为 2
  74. print(item_with_higher_weight.weight) # 输出 2
  75. # 7、颜色深度调整(模拟颜色通道值的左移)
  76. class Color:
  77. def __init__(self, r, g, b):
  78. self.r = r
  79. self.g = g
  80. self.b = b
  81. def __lshift__(self, other):
  82. # 假设 other 是亮度增加的因子(注意:这里需要确保值在有效范围内)
  83. return Color(min(self.r << other, 255), min(self.g << other, 255), min(self.b << other, 255))
  84. if __name__ == '__main__':
  85. red = Color(255, 0, 0)
  86. brighter_red = red << 1 # 增加亮度
  87. print(brighter_red.r, brighter_red.g, brighter_red.b) # 输出:255 0 0
  88. # 8、频率调整(模拟音频信号频率的左移)
  89. class AudioSignal:
  90. # 这里仅作为示例,实际音频处理会更复杂
  91. def __init__(self, frequencies):
  92. self.frequencies = frequencies
  93. def __lshift__(self, other):
  94. # 假设 other 是频率增加的因子(这在实际中是不准确的,仅作示例)
  95. return AudioSignal([freq * (2 ** other) for freq in self.frequencies])
  96. if __name__ == '__main__':
  97. signal = AudioSignal([100, 200, 300])
  98. higher_freq_signal = signal << 1 # 模拟频率加倍
  99. print(higher_freq_signal.frequencies) # 输出:[200, 400, 600]
  100. # 9、队列元素左移(删除头部元素并在尾部添加新元素)
  101. class Queue:
  102. def __init__(self):
  103. self.items = []
  104. def enqueue(self, item):
  105. self.items.append(item)
  106. def dequeue(self):
  107. if self.is_empty():
  108. raise IndexError("Queue is empty")
  109. return self.items.pop(0)
  110. def is_empty(self):
  111. return len(self.items) == 0
  112. # 模拟左移(删除头部并添加新元素)
  113. def __lshift__(self, new_item):
  114. self.dequeue()
  115. self.enqueue(new_item)
  116. if __name__ == '__main__':
  117. q = Queue()
  118. q.enqueue(1)
  119. q.enqueue(2)
  120. q.enqueue(3)
  121. print(q.items) # 输出 [1, 2, 3]
  122. q << 4 # 删除1并添加4
  123. print(q.items) # 输出 [2, 3, 4]
  124. # 10、价格调整(模拟折扣)
  125. class Price:
  126. def __init__(self, value):
  127. self.value = value
  128. def __lshift__(self, discount_factor):
  129. # 假设 discount_factor 是折扣的百分比(例如,左移1位代表打五折)
  130. # 注意:这里的实现仅作为示例,真实的折扣计算会更复杂
  131. return Price(self.value * (1 - discount_factor / 100))
  132. if __name__ == '__main__':
  133. original_price = Price(100)
  134. discounted_price = original_price << 50 # 假设代表打五折
  135. print(discounted_price.value) # 输出 50.0
  136. # 11、时间线事件的前移
  137. class TimelineEvent:
  138. def __init__(self, name, timestamp):
  139. self.name = name
  140. self.timestamp = timestamp
  141. def __lshift__(self, time_delta):
  142. # 将事件前移指定的时间量
  143. self.timestamp -= time_delta
  144. if __name__ == '__main__':
  145. event = TimelineEvent('Meeting', datetime.now())
  146. print(event.timestamp) # 输出当前时间
  147. event << timedelta(hours=1) # 将事件前移1小时
  148. print(event.timestamp) # 输出前移1小时后的时间
  149. # 12、图形界面中的元素左移
  150. class GUIElement:
  151. def __init__(self, x, y):
  152. self.x = x
  153. self.y = y
  154. def __lshift__(self, shift_amount):
  155. # 将元素向左移动指定的像素量
  156. self.x = max(0, self.x - shift_amount) # 确保元素不会移出容器的左侧边界
  157. def __repr__(self):
  158. # 为了更友好地打印GUIElement对象
  159. return f"GUIElement(x={self.x}, y={self.y})"
  160. # 假设的GUI容器类(仅用于演示)
  161. class GUIContainer:
  162. def __init__(self):
  163. self.elements = []
  164. def add_element(self, element):
  165. # 添加元素到容器中(这里只是简单地将元素添加到列表中)
  166. self.elements.append(element)
  167. # 主程序
  168. if __name__ == '__main__':
  169. # 创建一个GUI容器
  170. container = GUIContainer()
  171. # 创建一个GUI元素(按钮)并添加到容器中(虽然在这里我们并不真正添加到GUI中)
  172. button = GUIElement(100, 50)
  173. # 假设有一个add_element方法添加到容器中(这里我们手动调用)
  174. container.add_element(button)
  175. # 将按钮向左移动20像素
  176. button << 20 # 调用__lshift__方法
  177. # 打印按钮的新位置
  178. print(button) # 输出类似:GUIElement(x=80, y=50)

46、__lt__方法

46-1、语法
  1. __lt__(self, other, /)
  2. Return self < other
46-2、参数

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

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

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

46-3、功能

        用于定义对象之间“小于”关系的行为。

46-4、返回值

        返回一个布尔值(True或False),表示self是否小于other。

46-5、说明

        如果没有在类中定义__lt__方法,并且尝试使用<运算符对其实例进行比较,将会引发一个TypeError,除非该类的实例是某个内置类型的子类(如int、float、str等),这些内置类型已经定义了它们自己的__lt__方法。

46-6、用法
  1. # 046、__lt__方法:
  2. # 1、自定义整数类
  3. class MyInt:
  4. def __init__(self, value):
  5. self.value = value
  6. def __lt__(self, other):
  7. if isinstance(other, MyInt):
  8. return self.value < other.value
  9. elif isinstance(other, int):
  10. return self.value < other
  11. else:
  12. raise TypeError("Unsupported operand types for <: 'MyInt' and '{}'".format(type(other).__name__))
  13. if __name__ == '__main__':
  14. a = MyInt(5)
  15. b = MyInt(10)
  16. print(a < b) # True
  17. # 2、自定义字符串长度比较
  18. class StringLength:
  19. def __init__(self, s):
  20. self.s = s
  21. def __lt__(self, other):
  22. if isinstance(other, StringLength):
  23. return len(self.s) < len(other.s)
  24. elif isinstance(other, int):
  25. return len(self.s) < other
  26. else:
  27. raise TypeError("Unsupported operand types for <: 'StringLength' and '{}'".format(type(other).__name__))
  28. if __name__ == '__main__':
  29. s1 = StringLength("apple")
  30. s2 = StringLength("banana")
  31. print(s1 < s2) # True
  32. # 3、自定义日期类
  33. from datetime import date
  34. class MyDate:
  35. def __init__(self, year, month, day):
  36. self.date = date(year, month, day)
  37. def __lt__(self, other):
  38. if isinstance(other, MyDate):
  39. return self.date < other.date
  40. else:
  41. raise TypeError("Unsupported operand types for <: 'MyDate' and '{}'".format(type(other).__name__))
  42. if __name__ == '__main__':
  43. d1 = MyDate(2024, 3, 13)
  44. d2 = MyDate(2024, 6, 4)
  45. print(d1 < d2) # True
  46. # 4、自定义二维点类
  47. class Point:
  48. def __init__(self, x, y):
  49. self.x = x
  50. self.y = y
  51. def __lt__(self, other):
  52. if isinstance(other, Point):
  53. return (self.x, self.y) < (other.x, other.y)
  54. else:
  55. raise TypeError("Unsupported operand types for <: 'Point' and '{}'".format(type(other).__name__))
  56. if __name__ == '__main__':
  57. p1 = Point(3, 6)
  58. p2 = Point(5, 11)
  59. print(p1 < p2) # True
  60. # 5、自定义矩形面积比较
  61. class Rectangle:
  62. def __init__(self, width, height):
  63. self.width = width
  64. self.height = height
  65. @property
  66. def area(self):
  67. return self.width * self.height
  68. def __lt__(self, other):
  69. if isinstance(other, Rectangle):
  70. return self.area < other.area
  71. else:
  72. raise TypeError("Unsupported operand types for <: 'Rectangle' and '{}'".format(type(other).__name__))
  73. if __name__ == '__main__':
  74. rect1 = Rectangle(3, 6)
  75. rect2 = Rectangle(5, 11)
  76. print(rect1 < rect2) # True
  77. # 6、自定义字典按值排序比较(仅比较第一个值)
  78. class ValueSortedDict:
  79. def __init__(self, dict_items):
  80. self.dict_items = sorted(dict_items.items(), key=lambda x: x[1])
  81. def __lt__(self, other):
  82. if isinstance(other, ValueSortedDict):
  83. return self.dict_items[0][1] < other.dict_items[0][1]
  84. else:
  85. raise TypeError("Unsupported operand types for <: 'ValueSortedDict' and '{}'".format(type(other).__name__))
  86. if __name__ == '__main__':
  87. dict1 = {'a': 10, 'b': 24}
  88. dict2 = {'c': 10, 'd': 8}
  89. vsd1 = ValueSortedDict(dict1)
  90. vsd2 = ValueSortedDict(dict2)
  91. print(vsd1 < vsd2) # False
  92. # 7、自定义分数类,按分数值比较
  93. from fractions import Fraction
  94. class FractionWrapper:
  95. def __init__(self, numerator, denominator):
  96. self.fraction = Fraction(numerator, denominator)
  97. def __lt__(self, other):
  98. if isinstance(other, FractionWrapper):
  99. return self.fraction < other.fraction
  100. elif isinstance(other, Fraction):
  101. return self.fraction < other
  102. else:
  103. raise TypeError("Unsupported operand types for <: 'FractionWrapper' and '{}'".format(type(other).__name__))
  104. if __name__ == '__main__':
  105. frac1 = FractionWrapper(10, 24)
  106. frac2 = FractionWrapper(3, 6)
  107. print(frac1 < frac2) # True
  108. # 8、自定义复数类,按模长比较
  109. import math
  110. class ComplexNumber:
  111. def __init__(self, real, imag):
  112. self.real = real
  113. self.imag = imag
  114. @property
  115. def modulus(self):
  116. return math.sqrt(self.real ** 2 + self.imag ** 2)
  117. def __lt__(self, other):
  118. if isinstance(other, ComplexNumber):
  119. return self.modulus < other.modulus
  120. else:
  121. raise TypeError("Unsupported operand types for <: 'ComplexNumber' and '{}'".format(type(other).__name__))
  122. if __name__ == '__main__':
  123. c1 = ComplexNumber(3, 6)
  124. c2 = ComplexNumber(5, 11)
  125. print(c1 < c2) # True
  126. # 9、自定义时间戳类,按时间先后比较
  127. from datetime import datetime, timezone
  128. class Timestamp:
  129. def __init__(self, timestamp):
  130. self.timestamp = datetime.fromtimestamp(timestamp, tz=timezone.utc)
  131. def __lt__(self, other):
  132. if isinstance(other, Timestamp):
  133. return self.timestamp < other.timestamp
  134. elif isinstance(other, datetime):
  135. return self.timestamp < other
  136. else:
  137. raise TypeError("Unsupported operand types for <: 'Timestamp' and '{}'".format(type(other).__name__))
  138. if __name__ == '__main__':
  139. ts1 = Timestamp(1609459200) # 2021-01-01 00:00:00 UTC
  140. ts2 = Timestamp(1609545600) # 2021-01-02 00:00:00 UTC
  141. print(ts1 < ts2) # True
  142. # 10、自定义二维点类,按字典序比较
  143. class Point2D:
  144. def __init__(self, x, y):
  145. self.x = x
  146. self.y = y
  147. def __lt__(self, other):
  148. if not isinstance(other, Point2D):
  149. return NotImplemented
  150. if self.x < other.x:
  151. return True
  152. elif self.x == other.x and self.y < other.y:
  153. return True
  154. return False
  155. def __repr__(self):
  156. return f"Point2D({self.x}, {self.y})"
  157. if __name__ == '__main__':
  158. p1 = Point2D(1, 2)
  159. p2 = Point2D(2, 1)
  160. p3 = Point2D(1, 3)
  161. print(p1 < p2) # True
  162. print(p1 < p3) # True
  163. print(p2 < p3) # False
  164. # 11、自定义图书类,按价格或出版时间比较
  165. from datetime import datetime
  166. class Book:
  167. def __init__(self, title, author, price, publish_date):
  168. self.title = title
  169. self.author = author
  170. self.price = price
  171. self.publish_date = datetime.strptime(publish_date, '%Y-%m-%d')
  172. def __repr__(self):
  173. return f"Book(title={self.title}, author={self.author}, price={self.price}, publish_date={self.publish_date.strftime('%Y-%m-%d')})"
  174. def __lt_by_price__(self, other):
  175. if not isinstance(other, Book):
  176. return NotImplemented
  177. return self.price < other.price
  178. def __lt_by_publish_date__(self, other):
  179. if not isinstance(other, Book):
  180. return NotImplemented
  181. return self.publish_date < other.publish_date
  182. if __name__ == '__main__':
  183. book1 = Book("Python Programming", "Alice", 39.99, "2022-01-01")
  184. book2 = Book("Java for Beginners", "Bob", 29.99, "2021-05-15")
  185. book3 = Book("Database Management", "Charlie", 49.99, "2022-06-30")
  186. # 按价格比较
  187. print(book1.__lt_by_price__(book2)) # True,因为book1的价格比book2高
  188. print(book2.__lt_by_price__(book3)) # True,因为book2的价格比book3低
  189. # 按出版时间比较
  190. print(book1.__lt_by_publish_date__(book2)) # False,因为book1的出版时间比book2晚
  191. print(book2.__lt_by_publish_date__(book3)) # True,因为book2的出版时间比book3早
  192. # 12、自定义学生类,按成绩比较
  193. class Student:
  194. def __init__(self, name, score):
  195. self.name = name
  196. self.score = score
  197. def __repr__(self):
  198. return f"Student(name={self.name}, score={self.score})"
  199. def __lt__(self, other):
  200. if not isinstance(other, Student):
  201. return NotImplemented
  202. return self.score < other.score
  203. if __name__ == '__main__':
  204. student1 = Student("Myelsa", 85)
  205. student2 = Student("Bruce", 90)
  206. student3 = Student("Jimmy", 85)
  207. # 按成绩比较
  208. print(student1 < student2) # True,因为student1的成绩比student2低
  209. print(student1 < student3) # False,因为student1和student3的成绩相同
  210. print(student2 < student3) # False,因为student2的成绩比student3高

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

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

/ 登录

评论记录:

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

分类栏目

后端 (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