目錄
一、概述
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高