Python魔法方法(持續(xù)更新)
簡(jiǎn)介
魔法方法是python內(nèi)置方法凡涩,不需要主動(dòng)調(diào)用,存在的目的是為了給python的解釋器進(jìn)行調(diào)用疹蛉,幾乎每個(gè)魔法方法都有一個(gè)對(duì)應(yīng)的內(nèi)置函數(shù)活箕,或者運(yùn)算符,當(dāng)我們對(duì)這個(gè)對(duì)象使用這些函數(shù)或者運(yùn)算符時(shí)就會(huì)調(diào)用類中的對(duì)應(yīng)魔法方法可款,可以理解為重寫這些python的內(nèi)置函數(shù)育韩。魔法方法的形式通常是__str__
是左右兩個(gè)下劃線通常是在類中
__len__
方法
__len__
魔法方法是可以使得len()方法使用在對(duì)象上,下面這個(gè)例子是模擬撲克牌
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函數(shù)查看fd對(duì)象的長(zhǎng)度
52
namedtuple()
方法作用是返回一個(gè)只攜帶屬性的對(duì)象闺鲸,如果你需要一個(gè)對(duì)象筋讨,同時(shí)這個(gè)對(duì)象中只有少量屬性那么可以嘗試使用這個(gè)方法。下面是官方文檔給的例子摸恍,可以通過下標(biāo)的形式取得屬性
>>> # 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__
擁有此方法的對(duì)象可以通過的使用列表的形式進(jìn)行對(duì)象操作悉罕,如:切片,下標(biāo)取值
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>立镶,雖然可以通過循環(huán)的形式取出對(duì)象中值壁袄,但并不代表它是一個(gè)可迭代對(duì)象,即使你在方法中返回的是字符串也可以循環(huán)媚媒,不過字符串循環(huán)會(huì)一直無限循環(huán)下去嗜逻,直到你手動(dòng)停止。<font color="red">主要原因是欣范,因?yàn)樵谑褂肙bj[key]時(shí)变泄,python解釋器自動(dòng)幫你調(diào)用了__getitem__(self,item)
方法,所以只要不使用item這個(gè)參數(shù)恼琼,無論你傳什么參數(shù)都不會(huì)報(bào)錯(cuò)妨蛹,返回什么值是有你決定的</font>
>>> isinstance(fd, collections.Iterable)
False
class A:
def __getitem__(self, item):
print("我被調(diào)用了")
return item
if __name__ == '__main__':
a = A()
print(a["aaaa"])
# output
# 我被調(diào)用了
# aaaa
__abs__
方法
__abs__
擁有此方法的可以直接使用abs()方法, 下面這個(gè)列子是模擬二維向量
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__
方法
擁有此方法的可以使得類的實(shí)例進(jìn)行相加晴竞,類似重載運(yùn)算符
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):
# 相當(dāng)于java中的toString方法, 稍后會(huì)講這個(gè)方法
return "Vector(%s, %s)" % (self.x, self.y)
>>> v1 = Vector(1, 2)
>>> v2 = Vector(3, 1)
>>> v1 + v2
Vector(4, 3)
即我可以通過修改類中的__add__
方法來重載+
運(yùn)算符