《流暢的python》一書是python入門之後高階的一本好書。它不是一本完備的python手冊,而是強調python作為程式語言獨有的特性。這些特性或者是python獨有的,或者是其它程式語言裡很少見的。在接下來的一段時間,我會整理這本書的筆記,大家相互學習,共同進步。
最簡單的兩個變數a,b交換value:
其它語言大部分需要用到臨時變數,例如:
$a = 100;
$b = 200;
$c = $a;
$b = $a;
$a = $c;
echo $a,$b;#200100
複製**
$a 與$b交換值,需要借助臨時$c來實現。如果是python呢?
a,b = 100,200
a,b = b,a
print(a,b)#200 100
複製**
對,這就是pythonic的**,是不是很簡單易讀?來個更直觀的栗子:
定義一副撲克牌
import collections
card = collections.namedtuple('card',['rank','suit'])
class
frenchdeck:
rank = [str(i) for i in range(2,11)]+'jqka'
suit = 'spades diamonds clubs hearts'.split()
def__init__
(self):
self._cards = [card(rank,suit) for suit in self.suit for card in self.rank]
def__len__
(self):
return len(self._cards)
def__getitem__
(self,position):
return self._cards[position]
複製**
短短十來行**就定義 了一副撲克牌,是不是覺得很輕鬆呢?
注意:collections.namedtuple()方法用以構建只有少數屬性沒有方法的物件,例如資料庫條目。在python2中定義乙個類需要顯式的繼承object,定義類名時需要frenchdeck(object)繼承的父類,python3則預設繼承object不用再寫object了。
python定義列表的特別之處莫過於它的列表生成式了,簡單明瞭, 敲起來也方便。其中:
rank = [str(i) for i in range(2,11)]+'jqka'
複製**
使用列表生成式定義了撲克牌中的2~a
suit = 'spades diamonds clubs hearts'.split()複製**
定義了撲克牌的四種花色
self._cards = [card(rank,suit) for suit in self.suit for card in self.rank]複製**
再次使用列表生成式將花色與點數組合起來。其實三行**已經將撲克牌定義完了,列表生成式的優點就在於可以用極短的**,完成列表的建立。假設使用迭代的方式定義這副撲克牌,很顯然,**就不會是三行了。
好了,既然有了一副撲克牌,那我們就要來賭點大的了。
#1.紙牌數量
#因為我們重新定義了特殊方法__len__,當我們需要紙牌數量的時候直接使用len()方法就可以。
#特殊方法的存在是給python直譯器使用的,你不需要呼叫它們,也就是說沒有my_obj.__len__()這種寫法,
#而應該使用len(my_obj),在執行len(my_obj)的時候,如果my_obj是你自己定義的物件,那麼python會去
#呼叫由你實現的__len__方法
deck = frenchdeck()
print(len(deck))#52
#抽取第一張或者最後一張
deck[0]或deck[-1]
#隨機抽取一張
from random import choice
choice(deck)
#由於__getitem__方法把操作交給了self._cards列表,所以deck支援切片和迭代操作
#取出四張a(切片)
deck[12::13]
#迭代for card in deck:
print(card)
#反向迭代
for card in reversed(deck):
print(card)
#排序(公升序)
suit_value = dict(spades=3,hearts=2,diamonds=1,clubs=0)
def spades_high(card):
rank_value = frenchdeck.rank.index(card.rank)
return rank_value * len(suit_value) + suit_value[card.suit]
for card in sorted(deck,key=spades_high):
print(card)
複製**
如__getitem__這些帶雙下劃線的方法,我們稱之為特殊方法,特殊方法的存在是為了被直譯器呼叫的,你自己並不需要呼叫它們。很多時候,特殊方法的呼叫是隱式的,例如迴圈語句,for i in x:這個語句,背後其實使用的是iter(x),而這個函式的背後是x.__iter__()方法,當然,前提是__iter__這個方法被實現了。
通常來說,**無需直接使用特殊方法。除非有大量的元程式設計存在,直接呼叫特殊方法的頻率應該遠遠低於你去實現它們的次數。唯一例外的可能是__init__方法,你的**裡可能經常會用到它,目的是在你自己的子類的__init__方法中呼叫超類的構造器。
此外,不要自己想當然的隨意新增特殊方法,比如__foo__之類。因為雖然現在這個名字沒有被python內部使用,以後就不一定了。
流暢的python python資料模型
python最好的品質之一就是一致性。初步接觸python可能會len collection 而不是collection.len 覺得不適應,這是通常所說的 python風格 pythonic 的關鍵,體現在python的資料模型上,資料模型是對python框架的描述,它規範了這門語言自身構建模組的...
python 資料模型
usr bin env python coding utf 8 import collections card collections.namedtuple card rank suit class frenchdeck 通過實現特殊方法利用python資料模型的好處 1.作為你類的使用者,他們不必...
Python資料模型
1 了解python資料模型和介面的概念 2 掌握特殊方法的定義,作用和基本用法。1 資料模型 data model 是資料特徵的抽象,這裡是對python框架的描述。資料模型規範了python自身構建模組的介面,模組包括但不限於序列 迭代器 函式 類和上下文管理器。2 介面 介面泛指實體把自己提供...