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

目录

一、概述

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、语法
__length_hint__(self, /)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、用法
# 044、__length_hint__方法:
# 1、简单的列表包装器
class MyListWrapper:def __init__(self, lst):self.lst = lstdef __length_hint__(self):return len(self.lst)# 2、迭代器长度提示
class MyIterator:def __init__(self, numbers):self.numbers = numbersself.index = 0def __iter__(self):return selfdef __next__(self):if self.index < len(self.numbers):result = self.numbers[self.index]self.index += 1return resultraise StopIterationdef __length_hint__(self):return len(self.numbers) - self.index# 3、动态生成的序列
class DynamicSequence:def __init__(self, start, end):self.start = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.start > self.end:raise StopIterationcurrent = self.startself.start += 1return currentdef __length_hint__(self):return self.end - self.start + 1 if self.start <= self.end else 0# 4、缓存长度的迭代器
class CachedLengthIterator:def __init__(self, iterable):self.iterable = iterableself._length = Nonedef __iter__(self):return iter(self.iterable)def __length_hint__(self):if self._length is None:self._length = sum(1 for _ in self.iterable)return self._length# 5、生成器长度提示(通常不准确,因为生成器是动态的)
def my_generator(n):for i in range(n):yield i
class GeneratorWrapper:def __init__(self, generator_func, *args, **kwargs):self.generator = generator_func(*args, **kwargs)self._hint = Nonedef __iter__(self):return iter(self.generator)def __length_hint__(self):if self._hint is None:# 注意:这只是一个示例,对于真正的生成器可能不准确self._hint = sum(1 for _ in self.generator)return self._hint# 使用示例:GeneratorWrapper(my_generator, 10)# 6、模拟数据库查询结果
class DatabaseQueryResult:def __init__(self, count):self.count = countdef __length_hint__(self):return self.count# 7、文件行数预估(基于文件大小)
class FileLineCounterApprox:def __init__(self, file_path, avg_line_length=100):  # 假设平均行长为100字节self.file_path = file_pathself.avg_line_length = avg_line_lengthdef __length_hint__(self):with open(self.file_path, 'rb') as file:return file.seek(0, 2) // self.avg_line_length  # 粗略估计# 8、树形结构节点数预估
class TreeNode:def __init__(self, value, children=None):self.value = valueself.children = children if children is not None else []def __length_hint__(self):# 假设这是一个完全二叉树,用于示例return (2 ** self.depth()) - 1 if self.is_full_binary_tree() else "unknown"def depth(self):# 需要实现一个计算树深度的函数passdef is_full_binary_tree(self):# 需要实现一个检查树是否是完全二叉树的函数pass# 注意:在实际应用中,树的长度(即节点数)可能需要递归遍历才能准确计算# 9、网络请求结果集大小预估
class APIResult:def __init__(self, response_headers):self.response_headers = response_headersdef __length_hint__(self):# 假设API响应头中包含了一个关于结果集大小的字段content_length = self.response_headers.get('X-Result-Set-Size', None)return int(content_length) if content_length is not None and content_length.isdigit() else "unknown"# 注意:这个预估是基于假设的HTTP头字段,实际API可能不会有这样的字段# 10、流式数据处理长度提示
class StreamProcessor:def __init__(self, stream):self.stream = streamself._processed_count = 0def process(self, chunk_size=1024):# 处理流数据,这里只是模拟for _ in range(chunk_size):# 假设每次处理一个数据单元self._processed_count += 1def __length_hint__(self):# 流数据长度通常未知,但可以提供已处理的数量return self._processed_count# 注意:流数据的长度通常是未知的,除非有额外的信息或上下文# 11、自定义集合大小预估
class CustomSet:def __init__(self, iterable=()):self._set = set(iterable)self._hint = Nonedef add(self, item):self._set.add(item)self._hint = None  # 清除长度提示缓存def remove(self, item):self._set.remove(item)self._hint = Nonedef __iter__(self):return iter(self._set)def __len__(self):return len(self._set)def __length_hint__(self):if self._hint is None:self._hint = len(self)  # 只有在需要时才计算长度return self._hint# 注意:在实际应用中,集合的大小可以直接通过len()函数获取,但这里展示了如何使用__length_hint__进行缓存

45、__lshift__方法

45-1、语法
__lshift__(self, other, /)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、用法
# 045、__lshift__方法:
# 1、二进制位移
class BinaryShift:def __init__(self, value):self.value = valuedef __lshift__(self, other):return BinaryShift(self.value << other)
if __name__ == '__main__':a = BinaryShift(4)b = a << 2  # 相当于 4 << 2 = 16print(b.value)  # 输出 16# 2、整数列表左移
class IntList:def __init__(self, values):self.values = valuesdef __lshift__(self, other):if other < 0 or other >= len(self.values):raise ValueError("Invalid shift amount")return IntList(self.values[other:] + self.values[:other])
if __name__ == '__main__':lst = IntList([3, 5, 6, 8, 10, 11, 24])shifted = lst << 2  # 相当于 [6, 8, 10, 11, 24, 3, 5]print(shifted.values)  # 输出 [6, 8, 10, 11, 24, 3, 5]# 3、字符串左移
class StringShift:def __init__(self, value):self.value = valuedef __lshift__(self, other):if other < 0:return StringShift(self.value[-other:] + self.value[:-other])elif other >= len(self.value):return StringShift(self.value)else:return StringShift(self.value[other:] + self.value[:other])
if __name__ == '__main__':s = StringShift("hello")shifted = s << 2  # 相当于 "llohe"print(shifted.value)  # 输出 "llohe"# 4、时间戳左移(模拟时间偏移)
from datetime import datetime, timedelta
class TimestampShift:def __init__(self, timestamp):self.timestamp = timestampdef __lshift__(self, other):# 假设 other 是天数return TimestampShift(self.timestamp + timedelta(days=other))
if __name__ == '__main__':now = datetime.now()ts = TimestampShift(now)future = ts << 10  # 10天后的时间print(future.timestamp)  # 输出10天后的日期时间# 5、图形对象的水平移动
class Shape:def __init__(self, x, y):self.x = xself.y = ydef __lshift__(self, other):return Shape(self.x + other, self.y)
if __name__ == '__main__':rect = Shape(10, 24)moved = rect << 5  # 向右移动5个单位print(moved.x, moved.y)  # 输出 15 24# 6、权重调整(模拟权重左移)
class WeightedItem:def __init__(self, value, weight):self.value = valueself.weight = weightdef __lshift__(self, other):# 假设 other 是权重增加的因子(例如,左移1位相当于权重乘以2)return WeightedItem(self.value, self.weight * (2 ** other))
if __name__ == '__main__':item = WeightedItem('apple', 1)item_with_higher_weight = item << 1  # 权重变为 2print(item_with_higher_weight.weight)  # 输出 2# 7、颜色深度调整(模拟颜色通道值的左移)
class Color:def __init__(self, r, g, b):self.r = rself.g = gself.b = bdef __lshift__(self, other):# 假设 other 是亮度增加的因子(注意:这里需要确保值在有效范围内)return Color(min(self.r << other, 255), min(self.g << other, 255), min(self.b << other, 255))
if __name__ == '__main__':red = Color(255, 0, 0)brighter_red = red << 1  # 增加亮度print(brighter_red.r, brighter_red.g, brighter_red.b)  # 输出:255 0 0# 8、频率调整(模拟音频信号频率的左移)
class AudioSignal:# 这里仅作为示例,实际音频处理会更复杂def __init__(self, frequencies):self.frequencies = frequenciesdef __lshift__(self, other):# 假设 other 是频率增加的因子(这在实际中是不准确的,仅作示例)return AudioSignal([freq * (2 ** other) for freq in self.frequencies])
if __name__ == '__main__':signal = AudioSignal([100, 200, 300])higher_freq_signal = signal << 1  # 模拟频率加倍print(higher_freq_signal.frequencies)  # 输出:[200, 400, 600]# 9、队列元素左移(删除头部元素并在尾部添加新元素)
class Queue:def __init__(self):self.items = []def enqueue(self, item):self.items.append(item)def dequeue(self):if self.is_empty():raise IndexError("Queue is empty")return self.items.pop(0)def is_empty(self):return len(self.items) == 0# 模拟左移(删除头部并添加新元素)def __lshift__(self, new_item):self.dequeue()self.enqueue(new_item)
if __name__ == '__main__':q = Queue()q.enqueue(1)q.enqueue(2)q.enqueue(3)print(q.items)  # 输出 [1, 2, 3]q << 4  # 删除1并添加4print(q.items)  # 输出 [2, 3, 4]# 10、价格调整(模拟折扣)
class Price:def __init__(self, value):self.value = valuedef __lshift__(self, discount_factor):# 假设 discount_factor 是折扣的百分比(例如,左移1位代表打五折)# 注意:这里的实现仅作为示例,真实的折扣计算会更复杂return Price(self.value * (1 - discount_factor / 100))
if __name__ == '__main__':original_price = Price(100)discounted_price = original_price << 50  # 假设代表打五折print(discounted_price.value)  # 输出 50.0# 11、时间线事件的前移
class TimelineEvent:def __init__(self, name, timestamp):self.name = nameself.timestamp = timestampdef __lshift__(self, time_delta):# 将事件前移指定的时间量self.timestamp -= time_delta
if __name__ == '__main__':event = TimelineEvent('Meeting', datetime.now())print(event.timestamp)  # 输出当前时间event << timedelta(hours=1)  # 将事件前移1小时print(event.timestamp)  # 输出前移1小时后的时间# 12、图形界面中的元素左移
class GUIElement:def __init__(self, x, y):self.x = xself.y = ydef __lshift__(self, shift_amount):# 将元素向左移动指定的像素量self.x = max(0, self.x - shift_amount)  # 确保元素不会移出容器的左侧边界def __repr__(self):# 为了更友好地打印GUIElement对象return f"GUIElement(x={self.x}, y={self.y})"
# 假设的GUI容器类(仅用于演示)
class GUIContainer:def __init__(self):self.elements = []def add_element(self, element):# 添加元素到容器中(这里只是简单地将元素添加到列表中)self.elements.append(element)
# 主程序
if __name__ == '__main__':# 创建一个GUI容器container = GUIContainer()# 创建一个GUI元素(按钮)并添加到容器中(虽然在这里我们并不真正添加到GUI中)button = GUIElement(100, 50)# 假设有一个add_element方法添加到容器中(这里我们手动调用)container.add_element(button)# 将按钮向左移动20像素button << 20  # 调用__lshift__方法# 打印按钮的新位置print(button)  # 输出类似:GUIElement(x=80, y=50)

46、__lt__方法

46-1、语法
__lt__(self, other, /)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、用法
# 046、__lt__方法:
# 1、自定义整数类
class MyInt:def __init__(self, value):self.value = valuedef __lt__(self, other):if isinstance(other, MyInt):return self.value < other.valueelif isinstance(other, int):return self.value < otherelse:raise TypeError("Unsupported operand types for <: 'MyInt' and '{}'".format(type(other).__name__))
if __name__ == '__main__':a = MyInt(5)b = MyInt(10)print(a < b)  # True# 2、自定义字符串长度比较
class StringLength:def __init__(self, s):self.s = sdef __lt__(self, other):if isinstance(other, StringLength):return len(self.s) < len(other.s)elif isinstance(other, int):return len(self.s) < otherelse:raise TypeError("Unsupported operand types for <: 'StringLength' and '{}'".format(type(other).__name__))
if __name__ == '__main__':s1 = StringLength("apple")s2 = StringLength("banana")print(s1 < s2)  # True# 3、自定义日期类
from datetime import date
class MyDate:def __init__(self, year, month, day):self.date = date(year, month, day)def __lt__(self, other):if isinstance(other, MyDate):return self.date < other.dateelse:raise TypeError("Unsupported operand types for <: 'MyDate' and '{}'".format(type(other).__name__))
if __name__ == '__main__':d1 = MyDate(2024, 3, 13)d2 = MyDate(2024, 6, 4)print(d1 < d2)  # True# 4、自定义二维点类
class Point:def __init__(self, x, y):self.x = xself.y = ydef __lt__(self, other):if isinstance(other, Point):return (self.x, self.y) < (other.x, other.y)else:raise TypeError("Unsupported operand types for <: 'Point' and '{}'".format(type(other).__name__))
if __name__ == '__main__':p1 = Point(3, 6)p2 = Point(5, 11)print(p1 < p2)  # True# 5、自定义矩形面积比较
class Rectangle:def __init__(self, width, height):self.width = widthself.height = height@propertydef area(self):return self.width * self.heightdef __lt__(self, other):if isinstance(other, Rectangle):return self.area < other.areaelse:raise TypeError("Unsupported operand types for <: 'Rectangle' and '{}'".format(type(other).__name__))
if __name__ == '__main__':rect1 = Rectangle(3, 6)rect2 = Rectangle(5, 11)print(rect1 < rect2)  # True# 6、自定义字典按值排序比较(仅比较第一个值)
class ValueSortedDict:def __init__(self, dict_items):self.dict_items = sorted(dict_items.items(), key=lambda x: x[1])def __lt__(self, other):if isinstance(other, ValueSortedDict):return self.dict_items[0][1] < other.dict_items[0][1]else:raise TypeError("Unsupported operand types for <: 'ValueSortedDict' and '{}'".format(type(other).__name__))
if __name__ == '__main__':dict1 = {'a': 10, 'b': 24}dict2 = {'c': 10, 'd': 8}vsd1 = ValueSortedDict(dict1)vsd2 = ValueSortedDict(dict2)print(vsd1 < vsd2)  # False# 7、自定义分数类,按分数值比较
from fractions import Fraction
class FractionWrapper:def __init__(self, numerator, denominator):self.fraction = Fraction(numerator, denominator)def __lt__(self, other):if isinstance(other, FractionWrapper):return self.fraction < other.fractionelif isinstance(other, Fraction):return self.fraction < otherelse:raise TypeError("Unsupported operand types for <: 'FractionWrapper' and '{}'".format(type(other).__name__))
if __name__ == '__main__':frac1 = FractionWrapper(10, 24)frac2 = FractionWrapper(3, 6)print(frac1 < frac2)  # True# 8、自定义复数类,按模长比较
import math
class ComplexNumber:def __init__(self, real, imag):self.real = realself.imag = imag@propertydef modulus(self):return math.sqrt(self.real ** 2 + self.imag ** 2)def __lt__(self, other):if isinstance(other, ComplexNumber):return self.modulus < other.moduluselse:raise TypeError("Unsupported operand types for <: 'ComplexNumber' and '{}'".format(type(other).__name__))
if __name__ == '__main__':c1 = ComplexNumber(3, 6)c2 = ComplexNumber(5, 11)print(c1 < c2)  # True# 9、自定义时间戳类,按时间先后比较
from datetime import datetime, timezone
class Timestamp:def __init__(self, timestamp):self.timestamp = datetime.fromtimestamp(timestamp, tz=timezone.utc)def __lt__(self, other):if isinstance(other, Timestamp):return self.timestamp < other.timestampelif isinstance(other, datetime):return self.timestamp < otherelse:raise TypeError("Unsupported operand types for <: 'Timestamp' and '{}'".format(type(other).__name__))
if __name__ == '__main__':ts1 = Timestamp(1609459200)  # 2021-01-01 00:00:00 UTCts2 = Timestamp(1609545600)  # 2021-01-02 00:00:00 UTCprint(ts1 < ts2)  # True# 10、自定义二维点类,按字典序比较
class Point2D:def __init__(self, x, y):self.x = xself.y = ydef __lt__(self, other):if not isinstance(other, Point2D):return NotImplementedif self.x < other.x:return Trueelif self.x == other.x and self.y < other.y:return Truereturn Falsedef __repr__(self):return f"Point2D({self.x}, {self.y})"
if __name__ == '__main__':p1 = Point2D(1, 2)p2 = Point2D(2, 1)p3 = Point2D(1, 3)print(p1 < p2)  # Trueprint(p1 < p3)  # Trueprint(p2 < p3)  # False# 11、自定义图书类,按价格或出版时间比较
from datetime import datetime
class Book:def __init__(self, title, author, price, publish_date):self.title = titleself.author = authorself.price = priceself.publish_date = datetime.strptime(publish_date, '%Y-%m-%d')def __repr__(self):return f"Book(title={self.title}, author={self.author}, price={self.price}, publish_date={self.publish_date.strftime('%Y-%m-%d')})"def __lt_by_price__(self, other):if not isinstance(other, Book):return NotImplementedreturn self.price < other.pricedef __lt_by_publish_date__(self, other):if not isinstance(other, Book):return NotImplementedreturn self.publish_date < other.publish_date
if __name__ == '__main__':book1 = Book("Python Programming", "Alice", 39.99, "2022-01-01")book2 = Book("Java for Beginners", "Bob", 29.99, "2021-05-15")book3 = Book("Database Management", "Charlie", 49.99, "2022-06-30")# 按价格比较print(book1.__lt_by_price__(book2))  # True,因为book1的价格比book2高print(book2.__lt_by_price__(book3))  # True,因为book2的价格比book3低# 按出版时间比较print(book1.__lt_by_publish_date__(book2))  # False,因为book1的出版时间比book2晚print(book2.__lt_by_publish_date__(book3))  # True,因为book2的出版时间比book3早# 12、自定义学生类,按成绩比较
class Student:def __init__(self, name, score):self.name = nameself.score = scoredef __repr__(self):return f"Student(name={self.name}, score={self.score})"def __lt__(self, other):if not isinstance(other, Student):return NotImplementedreturn self.score < other.score
if __name__ == '__main__':student1 = Student("Myelsa", 85)student2 = Student("Bruce", 90)student3 = Student("Jimmy", 85)# 按成绩比较print(student1 < student2)  # True,因为student1的成绩比student2低print(student1 < student3)  # False,因为student1和student3的成绩相同print(student2 < student3)  # False,因为student2的成绩比student3高

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/22061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】pyinstaller打包时添加详细信息

在要被打包的py文件同级目录新建version.txt&#xff0c;写入以下内容 # UTF-8 # # For more details about fixed file info ffi see: # http://msdn.microsoft.com/en-us/library/aa381058.aspx # VSVersionInfo(ffiFixedFileInfo(filevers(1, 4, 0, 5),prodvers(1, 4, 0, 5…

AIGC 011-SAM第一个图像分割大模型-分割一切!

AIGC 011-SAM第一个图像分割大模型-分割一切&#xff01; 文章目录 0 论文工作1论文方法2 效果 0 论文工作 这篇论文介绍了 Segment Anything (SA) 项目&#xff0c;这是一个全新的图像分割任务、模型和数据集。SA 项目是一个具有里程碑意义的工作&#xff0c;它为图像分割领域…

迎七一党史知识竞赛答题怎么做

迎七一党史知识竞赛答题&#xff0c;不仅是对于党史知识的检验&#xff0c;更是对于参赛者学习态度和综合能力的考量。在参与这类竞赛时&#xff0c;我们需要做好充分的准备&#xff0c;掌握一定的答题技巧&#xff0c;才能取得好的成绩。 首先&#xff0c;我们要深入了解竞赛…

FFmpeg播放器的相关概念【1】

播放器框架 相关术语 •容器&#xff0f;文件&#xff08;Conainer/File&#xff09;&#xff1a;即特定格式的多媒体文件&#xff0c;比如mp4、flv、mkv等。 • 媒体流&#xff08;Stream&#xff09;&#xff1a;表示时间轴上的一段连续数据&#xff0c;如一段声音数据、一段…

UFS Explorer Professional Recovery: 如何从启用了 mSATA 缓存的 Drobo 设备中恢复数据

天津鸿萌科贸发展有限公司是 UFS Explorer Professional Recovery 数据恢复软件的授权代理商。 UFS Explorer Professional Recovery 数据恢复软件提供综合性的解决方案&#xff0c;用于解决复杂的数据恢复案例&#xff0c;包括那些采用特殊存储技术的案例&#xff0c;或介质受…

上海亚商投顾:创业板指震荡收涨 超70家ST股跌停

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡震荡&#xff0c;创业板指走势稍强&#xff0c;盘中一度涨超1%&#xff0c;黄白二线分化严重。算…

vue ts 导入 @/assets/ 红色显示的问题解决

vue ts 导入 /assets/ 红色显示的问题解决 一、问题描述 在使用的时候这样导入会出现如上的错误。 在使用的时候&#xff0c;导入的类型也没有对应的代码提示&#xff0c;说明导入有问题。 二、解决 在 tsconfig.json 中添加如下内容&#xff1a; {"compilerOptions&…

AI大模型探索之路-实战篇15: Agent智能数据分析平台之整合封装Tools和Memory功能代码

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…

46.ThreadPoolExcutor接口

线程池状态 ThreadPoolExcutor使用int高3位来表示线程池状态&#xff0c;低29位表示线程数量 状态高三位接收新任务处理阻塞队列任务说明RUNNING111YYSHUTDOWN000NY不会接收新任务&#xff0c;但会处理阻塞队列剩余任务&#xff0c;比较温和&#xff0c;已经提交的任务都会执…

C++ STL-迭代器函数对象适配器

目录 一.迭代器 二. 函数对象 三. 适配器 一.迭代器 是一种通用的指针类型&#xff0c;可以用来遍历 STL 容器中的元素。 具有以下作用和意义&#xff1a; 提供一种通用的方式来访问容器中的元素。允许对不同类型的容器进行统一的操作。增强了代码的灵活性和可扩展性。 一…

【C++题解】1085 - 寻找雷劈数

问题&#xff1a;1085 - 寻找雷劈数 类型&#xff1a;for循环 题目描述&#xff1a; 把整数 3025 从中剪开分为 30 和 25 两个数&#xff0c;此时再将这两数之和平方&#xff0c;计算结果又等于原数。 (3025)(3025)55553025 &#xff0c;这样的数叫“雷劈数”。 求所有符合这…

Photoshop版本选择及系统要求

1、ps2018cc/2020cc版本 适合新手&#xff0c;增加了很多智能化操作&#xff0c;非常方便好上手。 2020&#xff1a; 2、ps2015版本 cc2015版本不论是功能还是硬件上&#xff0c;都是不二选择&#xff0c;适合于配置较低的电脑&#xff0c;该有的基本功能它都有。 3、2021/2…

std::numeric_limits::max和宏定义重复报错问题

问题描述 今天在编译Beckhoff ADS开源组件的时候发现编译报错&#xff0c;报错代码如下 long AdsDevice::ReadReqEx2(uint32_t group, uint32_t offset, size_t length, void* buffer, uint32_t* bytesRead) const {if (length > std::numeric_limits<uint32_t>::ma…

Algorand 的复兴之路:改变游戏规则,打造 RWA 第一公链

TLDR 发布 AlgoKit 2.0&#xff0c;支持 Python 原生语言&#xff0c;打造开发者友好的开发环境&#xff0c;Algorand 的开发者社区规模迅速扩大。 升级共识激励机制&#xff0c;用 ALGO 奖励共识节点参与共识的执行&#xff0c;增加 ALGO 的应用场景&#xff0c;同时进一步确…

如何从官网下载 mysql 二进制安装包

一.下载二进行包 1. 官网网址: https://www.mysql.com/ 如图所示进入官网 2. 点击 DOWNLOADS ,进入如下图 在该页面找到 MySQL Community (GPL) Downloads 点进去 如上图页面&#xff0c;找到 MySQL Community Server 在点进去 下载 linux 通用版 点击最下面 Compressed …

(十四)统计学基础练习题八(选择题T351-400)

本文整理了统计学基础知识相关的练习题&#xff0c;共50道&#xff0c;适用于想巩固统计学基础或备考的同学。来源&#xff1a;如荷学数据科学题库&#xff08;技术专项-统计学三&#xff09;。序号之前的题请看往期文章。 351&#xff09; 352&#xff09; 353&#xff09; 3…

Jmeter实战教程入门讲解

前言 通过前面对Jmeter元件的讲解&#xff0c;大家应该都知道常用元件的作用和使用了。编写Jmeter脚本前我们需要知道Jmeter元件的执行顺序&#xff0c;可以看看我这篇性能测试学习之路&#xff08;三&#xff09;—初识Jmeter来了解下。下面我将以工作中的一个简单的实例带大…

企业打款验证API在Java、Python、PHP中的使用教程

随着企业银行账号数量的增加和银行间的连接方式不断丰富&#xff0c;企业在进行资金交易时需要确保所填写的收款方账户信息的准确性和合法性&#xff0c;以避免资金损失和风险。然而&#xff0c;由于银行数量众多、地域分布广泛&#xff0c;不同银行间的账户验证机制和信息交互…

vue前端实现页面禁止缩放 前端适配问题处理 前端项目多端适配解决方案

在前端项目中,如果一个系统页面可以缩放可能会导致多种异常情况,这些异常情况涉及到页面布局、元素尺寸、事件触发、响应式设计和用户体验等方面。 1.布局错乱:页面元素在缩放后可能会出现错位、重叠或部分隐藏的情况,导致页面布局混乱,影响用户对页面内容的理解和操作。这…

【云原生】kubernetes中secret原理详解与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…