Python魔法方法(持續更新)
簡介
魔法方法是python內置方法,不需要主動調用,存在的目的是爲了給python的解釋器進行調用,幾乎每個魔法方法都有一個對應的內置函數,或者運算符,當我們對這個對象使用這些函數或者運算符時就會調用類中的對應魔法方法,可以理解爲重寫這些python的內置函數。魔法方法的形式通常是__str__
是左右兩個下劃線通常是在類中
__len__
方法
__len__
魔法方法是可以使得len()方法使用在對象上,下面這個例子是模擬撲克牌
import collections
card = collections.namedtuple('card', ["rank", 'suit'])
class FrenchDeck:
ranks = [ str(n) for n in range(2, 11)] + list("JQKA")
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self._cards)
>>> fd = FrenchDeck()
>>> len(fd) # 可以直接使用len函數查看fd對象的長度
52
namedtuple()
方法作用是返回一個只攜帶屬性的對象,如果你需要一個對象,同時這個對象中只有少量屬性那麼可以嘗試使用這個方法。下面是官方文檔給的例子,可以通過下標的形式取得屬性
>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)
__getitem__
方法
__getitem__
擁有此方法的對象可以通過的使用列表的形式進行對象操作,如:切片,下標取值
class FrenchDeck:
ranks = [ str(n) for n in range(2, 11)] + list("JQKA")
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
>>> fd[0]
card(rank='2', suit='spades')
>>> fd[0:2]
[card(rank='2', suit='spades'), card(rank='3', suit='spades')]
>>> for i in fd:
print(i)
card(rank='2', suit='spades')
card(rank='3', suit='spades')
card(rank='4', suit='spades')
card(rank='5', suit='spades')
........
<font color="red">特別注意</font>,雖然可以通過循環的形式取出對象中值,但並不代表它是一個可迭代對象,即使你在方法中返回的是字符串也可以循環,不過字符串循環會一直無限循環下去,直到你手動停止。<font color="red">主要原因是,因爲在使用Obj[key]時,python解釋器自動幫你調用了__getitem__(self,item)
方法,所以只要不使用item這個參數,無論你傳什麼參數都不會報錯,返回什麼值是有你決定的</font>
>>> isinstance(fd, collections.Iterable)
False
class A:
def __getitem__(self, item):
print("我被調用了")
return item
if __name__ == '__main__':
a = A()
print(a["aaaa"])
# output
# 我被調用了
# aaaa
__abs__
方法
__abs__
擁有此方法的可以直接使用abs()方法, 下面這個列子是模擬二維向量
from math import hypot
class Vector:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __abs__(self):
# hypot返回x和y的平方和的平方根
return hypot(self.x, self.y)
>>> abs(Vector(1, 2)) # 返回向量(1, 2)的模
2.23606797749979
__add__
方法
擁有此方法的可以使得類的實例進行相加,類似重載運算符
from math import hypot
class Vector:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __abs__(self):
# hypot返回x和y的平方和的平方根
return hypot(self.x, self.y)
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Vector(x, y)
def __repr__(self):
# 相當於java中的toString方法, 稍後會講這個方法
return "Vector(%s, %s)" % (self.x, self.y)
>>> v1 = Vector(1, 2)
>>> v2 = Vector(3, 1)
>>> v1 + v2
Vector(4, 3)
即我可以通過修改類中的__add__
方法來重載+
運算符