Python中的魔法函數(shù)和魔法屬性用法示例
前言
Python 中的魔法函數(shù),也被稱為特殊方法或雙下劃線方法,是 Python 中一些特殊命名的函數(shù),它們以雙下劃線開頭和結(jié)尾。這些函數(shù)定義了對(duì)象在特定情況下的行為,例如創(chuàng)建、比較、運(yùn)算、迭代等。
魔法函數(shù)主要是為某些特殊需求而設(shè)計(jì)的。例如__str__() 和__repr__() 函數(shù)用于打印輸出對(duì)象的信息,__add__() 函數(shù)用于定義兩個(gè)對(duì)象相加的行為,__len__() 函數(shù)定義當(dāng)被 len() 調(diào)用時(shí)的行為等。Python 魔法函數(shù)是實(shí)現(xiàn) Python 語(yǔ)法糖的一種方式,提高代碼的可讀性和可維護(hù)性,比如對(duì)象相加,大家更習(xí)慣 c = a + b 的形式,如果用戶使用 a + b 能自動(dòng)調(diào)用 a.__add__(b) 的話,自然要方便很多了,而魔法函數(shù)正好有這種功能。
魔法函數(shù)
__init__
__init__ 對(duì)象初始化函數(shù),在創(chuàng)建實(shí)例化對(duì)象時(shí)自動(dòng)調(diào)用。這個(gè)最熟悉的就不多說(shuō)了。
class TestClass: def __init__(self, name): self.name = name obj = TestClass("Alice")
__str__
以用戶友好的方式返回對(duì)象的字符串表示,使用 str() 時(shí)自動(dòng)調(diào)用。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"({self.x}, {self.y})" p = PointClass(3, 4) print(p) # (3, 4)
__repr__
以開發(fā)者友好的方式返回對(duì)象的字符串表示,使用 repr() 時(shí)自動(dòng)調(diào)用。當(dāng)使用 print() 函數(shù)打印對(duì)象時(shí),首先調(diào)用的是 __str__ 方法,如果對(duì)象沒(méi)有定義 __str__ 方法,才會(huì)調(diào)用 __repr__ 方法。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"({self.x}, {self.y})" def __repr__(self): return f"Point({self.x}, {self.y})" p = PointClass(3, 4) print(p) # (3, 4) print(str(p)) # (3, 4) print(repr(p)) # Point(3, 4)
__len__
返回對(duì)象的長(zhǎng)度,使用 len() 自動(dòng)調(diào)用。
class ListClass: def __init__(self, items): self.items = items def __len__(self): return len(self.items) my_list = ListClass([1, 2, 3, 4, 5]) print(len(my_list)) # 5
__missing__
當(dāng)嘗試訪問(wèn)字典中不存在的鍵時(shí),如果定義了 __missing__
方法,它將被調(diào)用,而不是拋出 KeyError
。
class DictClass(dict): def __missing__(self, key): self[key] = "default" return "default" my_dict = DictClass({'a': 1, 'b': 2}) print(my_dict['c']) # default print(my_dict.keys()) # dict_keys(['a', 'b', 'c']) my_dict = dict({'a': 1, 'b': 2}) print(my_dict['c']) # KeyError: 'c'
__getitem__
獲取對(duì)象的指定元素,當(dāng)使用索引操作符[]
來(lái)訪問(wèn)對(duì)象的元素時(shí)自動(dòng)調(diào)用。
class DictClass: def __init__(self, items): self.items = items def __getitem__(self, key): return self.items.get(key) my_dict = DictClass({'a': 1, 'b': 2}) print(my_dict['a']) # 1
__setitem__
給對(duì)象的指定元素設(shè)置值,給對(duì)象設(shè)定值時(shí)自動(dòng)調(diào)用。
class DictClass: def __init__(self, items): self.items = items def __setitem__(self, key, value): self.items[key] = value my_dict = DictClass({'a': 1, 'b': 2}) my_dict['c'] = 3 print(my_dict.items) # {'a': 1, 'b': 2, 'c': 3}
__delitem__
刪除對(duì)象指定元素,使用 del 刪除對(duì)象元素時(shí)自動(dòng)調(diào)用。
class DictClass: def __init__(self, items): self.items = items def __delitem__(self, key): del self.items[key] my_dict = DictClass({'a': 1, 'b': 2}) del my_dict['a'] print(my_dict.items) # {'b': 2}
__contains__
判斷對(duì)象是否包含指定元素,使用 in 判斷時(shí)自動(dòng)調(diào)用。
class ListClass: def __init__(self, items): self.items = items def __contains__(self, item): return item in self.items my_list = ListClass([1, 2, 3, 4, 5]) print(3 in my_list) # True
__iter__
返回迭代器對(duì)象。
class ListClass: def __init__(self, items): self.items = items def __iter__(self): return iter(self.items) my_list = ListClass([1, 2, 3, 4, 5]) for item in my_list: print(item) # 依次輸出: 1, 2, 3, 4, 5
__next__
返回迭代器的下一個(gè)元素,循環(huán)遍歷獲取對(duì)象元素時(shí)自動(dòng)調(diào)用。
class ListClass: def __init__(self, items): self.items = items self.index = 0 def __iter__(self): return self def __next__(self): if self.index >= len(self.items): raise StopIteration value = self.items[self.index] self.index += 1 return value my_list = ListClass([1, 2, 3, 4, 5]) for item in my_list: print(item) # 依次輸出: 1, 2, 3, 4, 5
__eq__
判斷兩個(gè)對(duì)象是否相等,兩個(gè)對(duì)象使用 == 判斷時(shí)自動(dòng)調(diào)用。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y p1 = PointClass(3, 4) p2 = PointClass(3, 4) p3 = PointClass(5, 6) print(p1 == p2) # True print(p1 == p3) # False
__abs__
輸出對(duì)象的絕對(duì)值。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __abs__(self): return (self.x * self.x + self.y * self.y) ** 0.5 p1 = PointClass(3, 4) print(abs(p1)) # 5.0
__lt__
判斷一個(gè)對(duì)象是否小于另一個(gè)對(duì)象。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __lt__(self, other): return self.x < other.x and self.y < other.y p1 = PointClass(3, 4) p2 = PointClass(3, 4) p3 = PointClass(5, 6) print(p1 < p2) # False print(p1 < p3) # True
__le__
判斷一個(gè)對(duì)象是否小于或等于另一個(gè)對(duì)象。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __le__(self, other): return self.x <= other.x and self.y <= other.y p1 = PointClass(3, 4) p2 = PointClass(3, 4) p3 = PointClass(5, 6) print(p1 <= p2) # True print(p1 <= p3) # True
__gt__
判斷一個(gè)對(duì)象是否大于另一個(gè)對(duì)象。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __gt__(self, other): return self.x > other.x and self.y > other.y p1 = PointClass(3, 4) p2 = PointClass(3, 4) p3 = PointClass(1, 2) print(p1 > p2) # False print(p1 > p3) # True
__ge__
判斷一個(gè)對(duì)象是否大于或等于另一個(gè)對(duì)象。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __ge__(self, other): return self.x >= other.x and self.y >= other.y p1 = PointClass(3, 4) p2 = PointClass(3, 4) p3 = PointClass(1, 2) print(p1 >= p2) # True print(p1 >= p3) # True
__add__
定義對(duì)象的加法操作,對(duì)象之間使用 + 自動(dòng)調(diào)用。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return PointClass(self.x + other.x, self.y + other.y) def __str__(self): return f"({self.x}, {self.y})" p1 = PointClass(1, 2) p2 = PointClass(3, 4) print(p1 + p2) # (4, 6)
__sub__
定義對(duì)象的減法操作,對(duì)象之間使用 - 自動(dòng)調(diào)用。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __sub__(self, other): return PointClass(self.x - other.x, self.y - other.y) def __str__(self): return f"({self.x}, {self.y})" p1 = PointClass(1, 2) p2 = PointClass(3, 4) print(p1 - p2) # (-2, -2)
__mul__
定義對(duì)象的乘法操作,對(duì)象之間使用 * 自動(dòng)調(diào)用,可以根據(jù)操作數(shù)類型進(jìn)行對(duì)象乘法和數(shù)乘。
class PointClass: def __init__(self, x, y): self.x = x self.y = y def __mul__(self, other): if isinstance(other, PointClass): return PointClass(self.x * other.x, self.y * other.y) elif isinstance(other, int) or isinstance(other, float): return PointClass(self.x * other, self.y * other) else: raise TypeError(f"Unsupported operand type: {type(other)}") def __str__(self): return f"({self.x}, {self.y})" p1 = PointClass(1, 2) p2 = PointClass(3, 4) print(p1 * p2) # (3, 8) print(p1 * 3) # (3, 6) print(p1 * "t") # TypeError: Unsupported operand type: <class 'str'>
__call__
使對(duì)象可調(diào)用。
class Calculator: def __init__(self, x, y): self.x = x self.y = y def __call__(self): return self.x + self.y calc = Calculator(3, 4) result = calc() print(result) # 7
class Calculator: def __call__(self, a, b): return a + b calc = Calculator() result = calc(3, 4) print(result) # 7
__getattr__
在訪問(wèn)對(duì)象不存在的屬性時(shí)調(diào)用。
class Person: def __getattr__(self, name): return f"Attribute '{name}' does not exist." p = Person() print(p.age) # Attribute 'age' does not exist.
__setattr__
當(dāng)設(shè)置類實(shí)例屬性時(shí)自動(dòng)調(diào)用。
class Person: def __setattr__(self, name, value): print(f"Setting attribute '{name}' to '{value}'") super().__setattr__(name, value) p = Person() p.name = "Alice" # Setting attribute 'name' to 'Alice' print(p.name) # Alice
__delattr__
刪除對(duì)象屬性時(shí)自動(dòng)調(diào)用。
class Person: def __delattr__(self, name): print(f"Deleting attribute '{name}'") super().__delattr__(name) p = Person() p.name = "Alice" print(p.name) # Alice del p.name # Deleting attribute 'name' print(p.name) # AttributeError: 'Person' object has no attribute 'name
__enter__
__enter__() 方法用于進(jìn)入上下文管理器所定義的代碼塊之前執(zhí)行的操作。
__exit__
上下文管理器的 __exit__() 方法還有三個(gè)參數(shù),即異常類型、異常值和追蹤信息。如果在 with 語(yǔ)句塊中發(fā)生了異常,這些參數(shù)會(huì)傳遞給 __exit__() 方法,可以在該方法中進(jìn)行相關(guān)的處理。
__del__
當(dāng)對(duì)象不再被引用時(shí),Python的垃圾回收機(jī)制會(huì)調(diào)用這個(gè)方法。
class FileHandler: def __init__(self, filename): self.filename = filename def __enter__(self): print("goto __enter__ open file") self.file = open(self.filename, 'w', encoding='utf-8') return self.file def __exit__(self, exc_type, exc_val, exc_tb): print("goto __exit__ close file") self.file.close() def __del__(self): print("goto __del__ release resource") print("process start") with FileHandler("./test.txt") as f: f.write("hello world!\n") print("process end") # process start # goto __enter__ open file # goto __exit__ close file # goto __del__ release resource # process end
魔法屬性
__dict__
__dict__
包含通過(guò) __init__
方法初始化的屬性和值。
class TestClass: def __init__(self, name): self.name = name def test(self): self.age = 25 obj = TestClass("Alice") print(obj.__dict__) # {'name': 'Alice'} # print(TestClass.__dict__)
__slots__
內(nèi)置類屬性__slots__
是一個(gè)特殊的內(nèi)置類屬性,它可以用于定義類的屬性名稱的集合。一旦在類中定義了__slots__
屬性,Python 將限制該類的實(shí)例只能擁有__slots__
中定義的屬性。
class Person: __slots__ = ('name', 'age') def __init__(self, name, age): self.name = name self.age = age self.address = "" # AttributeError: 'Person' object has no attribute 'address' person = Person("Alice", 30) print(person.name) # 輸出 "Alice" print(person.age) # 輸出 30 print(person.__slots__) # ('name', 'age')
總結(jié)
到此這篇關(guān)于Python中的魔法函數(shù)和魔法屬性的文章就介紹到這了,更多相關(guān)Python魔法函數(shù)和魔法屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PyTorch模型轉(zhuǎn)換為ONNX格式實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家介紹了PyTorch模型轉(zhuǎn)換為ONNX格式實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04自然語(yǔ)言處理NLP TextRNN實(shí)現(xiàn)情感分類
這篇文章主要為大家介紹了自然語(yǔ)言處理NLP TextRNN實(shí)現(xiàn)情感分類示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04淺談Python任務(wù)自動(dòng)化工具Tox基本用法
這篇文章主要介紹了淺談Python任務(wù)自動(dòng)化工具Tox,tox 是一個(gè)管理測(cè)試虛擬環(huán)境的命令行工具, 它已存在多年且廣被開發(fā)者們使用,對(duì)Python任務(wù)自動(dòng)化工具Tox基本用法感興趣的朋友一起看看吧2022-06-06100行python代碼實(shí)現(xiàn)跳一跳輔助程序
這篇文章主要介紹了100行代碼實(shí)現(xiàn)跳一跳輔助程序,接下來(lái)要分享的是用“純軟件”的方法來(lái)玩“跳一跳”。本人只做過(guò)Android開發(fā),因此下面只給出Android平臺(tái)下的實(shí)現(xiàn)方法。需要的朋友可以參考下2018-01-01