我們看到 『python』可以用len()
或者arr[0]
,它們是怎麼實現的,其實就是兩個魔法方法__len__
和__getitem__
,用撲克牌的例子學習一下,我們知道知道撲克牌有花色(黑桃,紅桃,方塊,梅花),有大小(2 -10 jqka
),如何創造一套牌的物件呢?
首先學習collections
的namedtuple
,這是乙個快速建立物件,有少數屬性但是沒有方法的,進一步學習可以查相關文件。這個非常適合作我們一張牌的物件。所以建立一套牌物件**如下:
from collections import namedtuple
card = 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)
def __getitem__(self, item):
return self._cards[item]
上面是一套牌物件,有魔法方法__len__
,__getitem__
我們測試一下**
if __name__ == '__main__':
import random
deck = frenchdeck()
# 求長度
print("長度", len(deck))
# 索引
print("索引0", deck[0])
print("索引-1", deck[-1])
# 切片
print("切片", deck[1:4:2])
# 迭代
for card in deck:
print("迭代", card)
# 包含
print("包含", card("q", "hearts") in deck)
# 隨機選擇
print("隨機選擇", random.choice(deck))
# 排序 我們認為數字2最小 a最大 花色 黑桃》紅桃》方塊》梅花
def sort_help(card):
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
rank_val = deck.ranks.index(card.rank)
return rank_val * 4 + suit_values[card.suit]
for card in sorted(deck, key=sort_help):
print("排序", card)
我們可以把物件像陣列一樣操作,可以求長度,索引,迭代,包含,排序等。。。
我們用向量來舉例子,要實現一下需求
向量加法vector(2, 4) + vector(2, 1) = vector(4, 6)
向量乘法vector(3, 4) * 3 = vector(9, 12)
向量的模|vector(3, 4)| = 5
上面vector
類的實現要用到__repr__, __abs__, __add__, __mul__
**如下
from math import hypot
class vector:
def __init__(self, x: int = 0, y: int = 0):
self.x = x
self.y = y
def __repr__(self):
return "vector({}, {})".format(self.x, self.y)
# 求模
def __abs__(self) -> float:
return hypot(self.x, self.y)
# 求bool
def __bool__(self) -> bool:
return bool(abs(self))
# 相加
def __add__(self, other) :
x = self.x + other.x
y = self.y + other.y
return vector(x, y)
# 乘def __mul__(self, other):
return vector(self.x * other, self.y * other)我們
我們測試**
if __name__ == '__main__':
x1 = vector(3, 4)
x2 = vector(6, 8)
# __repr__ 和 __str__ 的區別
# __str__ 只有 str 或者 print被使用
# 如果只想實現乙個 __repr__是更好的選擇,因為如果乙個物件
# 沒有 __str__ 函式,而 python 又需要呼叫它的時候,直譯器會用 __repr__ 作為替代。
print(x1)
# 求模
print(abs(x1))
# 加print(x1 + x2)
# 乘print(x1 * 3)
# bool
print(bool(x1))
附上特殊方法一覽表:
小結:我們自定義資料可以表現和內建型別一樣,通過魔法方法實現。
__repr__
方便我們除錯和記錄日誌,__str__
來給終端使用者看。
記錄學習 《流暢的python》第一天,一定要堅持下去!
流暢的python 魔術方法
第一章 流暢的python 裡面的描述 python 的魔術方法 magic method 是特殊方法的暱稱。一般是用 雙下劃線 名稱 雙下劃線 形式來表示,整體念起來也拗口,所以也有人把這種特殊方法名為稱為 雙下方法 dunder method 有關於特殊方法一覽,可以參考data model t...
流暢的python學習1
usr bin env python3 coding utf 8 created on mon apr 20 21 08 08 2020 author root import collections card collections.namedtuple card rank suit class f...
推薦書籍《流暢的Python》
我剛學程式設計的時候,有位從事c 開發的好友,傳授我經驗 工作中80 的時間用著那常用的20 的語言知識,其他的等你需要的時候再去看就好了設想在初學python 或者其他語言 的時候只是去學習那20 常用的,如果再不願意去精進,那麼可能我永遠都不會有機會去了解描述符,也不會使用元類,最後成了乙個以為...