《流暢的python》之資料模型

2021-09-11 15:09:13 字數 3074 閱讀 2324

《流暢的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 介面 介面泛指實體把自己提供...