1. 程式人生 > >Fluent Python簡記

Fluent Python簡記

Fluent Python 筆記
一、序列(Sequence)
1、容器序列(Container sequences):list, tuple, collections.deque ...
2、平坦序列(Flat sequences):str, bytes, bytearray, memoryview, array.array

根據可不可變分類:
1)可變的序列:list, bytearray, array.array, collections.deque, memoryview
2)不可變序列:tuple, str, bytes

二、如何快速生成一個序列
1)列表推導(List Comprehensions)
2)生成器表示式(Generator Expressions)

推薦列表推導:
words = ['The','quick','BROWN','Fox','jumed','OVER','the','Lazy','DOG']
[word for word in words if word.islower()]
===========================================
['quick', 'jumed', 'the']

列表推導格式以 [] 為標誌,內容分為三部分 [A B C],A,B,C分別代表一個表示式,其中C可以省略。
對於上面的例子:
A:word
B:for word in words
C:if word.islower()

首先看B,B的格式一般為 for x in xxx,表示從一個序列中逐個選取元素,也就是常用的 for in 結構。可以有多個for in,比如 for x in xxx for y in yyy。使用多個for的時候,就會生成所有組合。

colors = ['black','white']
sizes = ['S','M','L']
tshirts = [(color, size) for color in colors for size in sizes]
tshirts
=========================
[('black', 'S'),
 ('black', 'M'),
 ('black', 'L'),
 ('white', 'S'),
 ('white', 'M'),
 ('white', 'L')]

然後看C,C提供一個判斷條件,格式一般為 if xxx,其中可以用到B所給出的x,用於選取符合條件的條目。可以省略,也就意味著使用B生成的所有條目。

最後看A,A格式隨意,可以使用B中給出的x(或者y),當然也可以不使用。

生成器表示式和列表推導唯一的不同是用 () 包圍而不是 [],如果不需要一次性生成整個列表,那麼用生成器表示式更好。(word for word in words if word.islower())
==========================================
<generator object <genexpr> at 0x000001B1C18094C0>

需要變成列表的時候也可以隨時呼叫 list() 函式轉化為列表。
list((word for word in words if word.islower()))
=================================================
['quick', 'jumed', 'the']

二、元組(Tuple)
元組的主要用途:
1)作為不可變的列表
2)作為沒有欄位名稱的記錄

元組解包:
lax_coordinates = (33.9425, -118.408055)
latitude, longitude = lax_coordinates
latitude
==========
33.9425

longitude
============
-118.408055

作為函式引數就地展開,在前面加*就可以了:
>>> divmod(20, 8)
(2, 4)
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)

具名元組(Named Tuples):
因為元組作為記錄比較好用,因此出現了 namedtuple,在 collections 模組中。
使用 namedtuple 建立的例項消耗的記憶體和普通元組相同,因為欄位的名字是儲存在類中的。他們使用的記憶體比普通的類要少,因為它們不用在每個例項的 __dict__ 中儲存屬性。
>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x y')
>>> p = Point(3, 4)
>>> p
Point(x=3, y=4)

namedtuple 有幾個有用的屬性和方法:
1)_fields 類屬性,儲存所有欄位名稱
>>> Point._fields
('x', 'y')

2)_make(iterable) 類方法,使用已經存在的序列或者 iterable 來建立 namedtuple
>>> point_tuple = (3, 4)
>>> p = Point._make(point_tuple)
>>> p
Point(x=3, y=4)

3)_asdict() 例項方法,返回一個 OrderedDict,對映名稱和對應的值。
>>> p._asdict()
OrderedDict([('x', 3), ('y', 4)])

三、切片(Slice)
切片是序列中非常常用的操作,基本格式是 seq[start:stop:step],其中step及之前的冒號均可以省略,表示 step 為1。start和stop也都可以省略,但是第一個冒號不能省略。start省略表示從頭開始,stop省略表示切到尾部。

切片操作適用於幾乎所有序列型別,如 list, tuple, str 等等。

Python 中表示範圍一般使用前閉後開 [start, stop),根據這兩個單詞也比較容易記憶。

切片的長度,自然也就是 stop - start。

四、字典(Dict)
1、構造方式示例:
>>> d1 = dict(one=1, two=2, three=3)
>>> d2 = {'one':1, 'two':2, 'three':3}
>>> d3 = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d4 = dict([('two',2), ('one', 1), ('three', 3)])
>>> d5 = dict({'three':3, 'one':1, 'two':2})
>>> d1 == d2 == d3 == d4 == d5
True

2、字典推導示例:
>>> d = {n: n ** 2 for n in range(5)}
>>> d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

3、處理缺失key值的幾種方法:
1)setdefault 方法
my_dict.setdefault(key, []).append(new_value)

等同於:
if key not in my_dict:
    my_dict[key] = []

my_dict[key].append(new_value)

2)defaultdict
如果一開始就知道這個字典可能經常找不到key,想提供一個預設值,那麼可以使用 defaultdict。
工作原理:當例項化一個 defaultdict 時,提供一個函式 default_factory,每次 __getitem__ 傳入不存在的 key 引數時,產生預設值。

3、常用對映模組:
1)collections.OrderedDict
根據插入順序來管理 key,遍歷 item 的順序可以預期。 popitem 預設返回第一個 item,但是如果呼叫
my_odict.popitem(last=True),則彈出最後一個新增的條目。

2)collections.Counter
持有每個 key 的數量,每次 update 一個已經有的 key 都會增加其數量。這個可以用來為可雜湊的物件計數,或者用來作為多重集合(每個元素可以出現多次)。
>>> import collections
>>> ct = collections.Counter('abracadabra')
>>> ct
Counter({'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
>>> ct.update('aaazzz')
>>> ct
Counter({'a': 8, 'z': 3, 'r': 2, 'b': 2, 'd': 1, 'c': 1})
>>> ct.most_common(2)
[('a', 8), ('z', 3)]

3)collections.UserDict
純 Python 實現的對映,和標準的 dict 工作方式一樣,設計用來被繼承的。

五、集合(Set)
集合的主要作用還是去重:
>>> l = ['spam', 'spam', 'eggs', 'spam']
>>> set(l)
{'spam', 'eggs'}
>>> list(set(l))
['spam', 'eggs']