Python中的魔法函數(shù)和魔法屬性用法示例
前言
Python 中的魔法函數(shù),也被稱為特殊方法或雙下劃線方法,是 Python 中一些特殊命名的函數(shù),它們以雙下劃線開頭和結(jié)尾。這些函數(shù)定義了對象在特定情況下的行為,例如創(chuàng)建、比較、運(yùn)算、迭代等。
魔法函數(shù)主要是為某些特殊需求而設(shè)計的。例如__str__() 和__repr__() 函數(shù)用于打印輸出對象的信息,__add__() 函數(shù)用于定義兩個對象相加的行為,__len__() 函數(shù)定義當(dāng)被 len() 調(diào)用時的行為等。Python 魔法函數(shù)是實(shí)現(xiàn) Python 語法糖的一種方式,提高代碼的可讀性和可維護(hù)性,比如對象相加,大家更習(xí)慣 c = a + b 的形式,如果用戶使用 a + b 能自動調(diào)用 a.__add__(b) 的話,自然要方便很多了,而魔法函數(shù)正好有這種功能。
魔法函數(shù)
__init__
__init__ 對象初始化函數(shù),在創(chuàng)建實(shí)例化對象時自動調(diào)用。這個最熟悉的就不多說了。
class TestClass:
def __init__(self, name):
self.name = name
obj = TestClass("Alice")
__str__
以用戶友好的方式返回對象的字符串表示,使用 str() 時自動調(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ā)者友好的方式返回對象的字符串表示,使用 repr() 時自動調(diào)用。當(dāng)使用 print() 函數(shù)打印對象時,首先調(diào)用的是 __str__ 方法,如果對象沒有定義 __str__ 方法,才會調(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__
返回對象的長度,使用 len() 自動調(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)嘗試訪問字典中不存在的鍵時,如果定義了 __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__
獲取對象的指定元素,當(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__
給對象的指定元素設(shè)置值,給對象設(shè)定值時自動調(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__
刪除對象指定元素,使用 del 刪除對象元素時自動調(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__
判斷對象是否包含指定元素,使用 in 判斷時自動調(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__
返回迭代器對象。
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__
返回迭代器的下一個元素,循環(huán)遍歷獲取對象元素時自動調(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__
判斷兩個對象是否相等,兩個對象使用 == 判斷時自動調(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__
輸出對象的絕對值。
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__
判斷一個對象是否小于另一個對象。
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__
判斷一個對象是否小于或等于另一個對象。
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__
判斷一個對象是否大于另一個對象。
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__
判斷一個對象是否大于或等于另一個對象。
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__
定義對象的加法操作,對象之間使用 + 自動調(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__
定義對象的減法操作,對象之間使用 - 自動調(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__
定義對象的乘法操作,對象之間使用 * 自動調(diào)用,可以根據(jù)操作數(shù)類型進(jìn)行對象乘法和數(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__
使對象可調(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__
在訪問對象不存在的屬性時調(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í)例屬性時自動調(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__
刪除對象屬性時自動調(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__() 方法還有三個參數(shù),即異常類型、異常值和追蹤信息。如果在 with 語句塊中發(fā)生了異常,這些參數(shù)會傳遞給 __exit__() 方法,可以在該方法中進(jìn)行相關(guān)的處理。
__del__
當(dāng)對象不再被引用時,Python的垃圾回收機(jī)制會調(diào)用這個方法。
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__ 包含通過 __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__是一個特殊的內(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python tkinter實(shí)現(xiàn)桌面軟件流程詳解
這篇文章主要介紹了Python tkinter做一個好用的桌面軟件,100%你會愛上它,文中的示例代碼講解詳細(xì),快跟小編一起動手試一試吧2022-10-10
pytorch中交叉熵?fù)p失函數(shù)的使用小細(xì)節(jié)
這篇文章主要介紹了pytorch中交叉熵?fù)p失函數(shù)的使用細(xì)節(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
Python scrapy爬取起點(diǎn)中文網(wǎng)小說榜單
爬蟲的基礎(chǔ)內(nèi)容已經(jīng)全部學(xué)玩,博主決定想著更加標(biāo)準(zhǔn)化以及實(shí)用能力更強(qiáng)的scrapy進(jìn)發(fā),今天記錄自己第一個scrapy爬蟲項(xiàng)目. scrapy爬取起點(diǎn)中文網(wǎng)24小時熱銷榜單,需要的朋友可以參考下2021-06-06
Python基于Google?Bard實(shí)現(xiàn)交互式聊天機(jī)器人
這篇文章主要為大家介紹了Python基于Google?Bard實(shí)現(xiàn)交互式聊天機(jī)器人示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Python發(fā)送郵件封裝實(shí)現(xiàn)過程詳解
這篇文章主要介紹了Python發(fā)送郵件封裝實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-05-05
使用python將CSV和Excel表格數(shù)據(jù)導(dǎo)入到Word表格
在不同格式的文檔之間進(jìn)行數(shù)據(jù)傳輸是非常重要的操作,例如將CSV和Excel表格數(shù)據(jù)導(dǎo)入到Word文檔中,不僅可以實(shí)現(xiàn)數(shù)據(jù)的有效整合與展示,還能極大地提升工作效率和文檔的專業(yè)性,本文將介紹如何使用Python將CSV和Excel表格數(shù)據(jù)導(dǎo)入到Word文檔中并創(chuàng)建表格2024-09-09
Python+JavaScript實(shí)現(xiàn)瀏覽器讀取本地excel數(shù)據(jù)
一般來說,為了網(wǎng)絡(luò)訪問安全,瀏覽器是不能直接加載本地文件的,本文主要討論研究一種非IE內(nèi)核瀏覽器讀取本地excel數(shù)據(jù)的方法,繞開這個限制,希望對大家有所幫助2025-09-09

