程式扎記: [ The python tutorial ] 5. Data Structures

標籤

2012年1月7日 星期六

[ The python tutorial ] 5. Data Structures


翻譯自 這裡
Data Structures :
這裡將之前你學到的一些知識做些延伸說明, 並加一些新的內容.

- More on Lists
串列物件具備某些函示可以使用, 底下為列表即簡單說明 :
list.append(x)
添加元素到串列尾端, 等同 a[len(a):] = [x]

list.extend(L)
將傳入的串列的元素加到外部呼叫 extend() 的串列, 等同 a[len(a):] = L

list.insert(i, x)
第一個參數為插入位置; 第二個為插入元素. 如 a.insert(0, x) 即是將元素放在串列的前端, a.insert(len(a), x) 就是將元素放在串列尾端 (等同 a.append(x)).

list.remove(x)
移除第一個串列元素的值是 x. 如果沒有該元素則會出現 ValueError.

list.pop([i])
將指定位置的元素移除並返回. 這裡的 '[' i ']' 指的是 optional, 當沒有給定 i 時則移除並返回串列最後一個元素.

list.index(x)
返回串列中第一個元素是 x 的位置, 如果該元素不存在則出現 ValueError.

list.count(x)
返回串列中元素的值是 x 的數目.

list.sort()
對串列中的元素進行排列.

list.reverse()
將串列中的元素排列順序顛倒.

底下為上面介紹函示使用範例 :


事實上串列比你想像中的還好用, 底下針對串列應用進行說明. 首先透過函式 append() 與 pop() 就可以使用串列模擬 堆疊 (Stack : Last-in, First-out) :


要透過串列本身的函式來模擬 佇列 (Queue : First-in, Last-out) 效率不好, 我們可以 import collections.deque 來幫助我們 :
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

如果你要建立一個平方元素的陣列, 一般你可以能會這做 :


在 Python 中提供語法蜜糖, 所以你可以在一句內完成 :
>>> squares2 = [ x**2 for x in range(10)]
>>> squares2
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

再來看一個例子, 如果你有兩個串列 x[]; y[], 你想利用這兩這串列組成一個新的串列且該串列為 x 與 y 串列的元素組合但同一個組合元素兩個值不同 :


事實上你也可以只用一句就完成 :
>>> [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

其實這些在 Python 稱作 "List comprehensions", 底下為更多範例說明 :


而你的函式呼叫在 List comprehension 也可以是巢狀 :
>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

接著我們要來針對 巢狀 的 "List comprehension" 進行範例說明, 首先考慮一個串列如下 :
>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]

如果你想要從每個元素的第 i 個子元素取出成為另一個串列的元素, 你可以使用如下巢狀用法 :


底下是如果你不使用 listcomp 可能的作法 :


在實際應用上, 你可以透過 zip() 函式完成上面要求 : (see Unpacking Argument Lists)
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

The del statement :
如果你要刪除串列或是串列中的元素, 可以使用關鍵字 del :


Tuples and Sequences :
之前我們介紹過 字串 與 串列 時有些特性如使用 index, slice 等的功能其實是來自於他們都是屬於 Sequence data (see Sequence Types — str, bytes, bytearray, list, tuple, range). 除了這兩種類型外, tuple 也是 Sequence data :
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

tuple 與 字串都是 immutable, 也就是你不能改變 tuple 內的元素. 另外在建立空的 tuple 或是 只含一個元素的 tuple 可以如下 (只有一個元素的 tuple 後面須跟著一個逗點, 說明他是 tuple!) :
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

另外如果你要 unpack 類型 sequence data 時, 可以使用關鍵字 =, 左邊給對應數目的變數, 右邊給 sequence data :


Sets :
Set 為一資料結構其中的元素不允許重複, 你可以使用 mathematical operations 像 Union, Intersection, Difference, 與 Symmetric difference 來操作它. 要建立 Set 可以使用 {} 包含元素或是使用函式 set(). 但是要注意如果要建立空 Set, 就只能使用 函式 set() 而不能使用 {} (裡面沒有元素), 後者會被當作 字典 物件, 是下一節要講的東西. 底下為 Set 物件使用範例 :


跟 list-comp 一樣, 你也可以這麼用 :
>>> a = {x for x in 'abraccadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

Dictionaries :
字典物件一個 Set 的 key 集合, 並對應到儲存的 value. key 是 Unique 但是 value 不必是. 你可以透過 {} 並在裡面用 key:value 形式存放 key 與 value 的 mapping, 多個 pair 可用 ',' 區隔. 假設你有一個 d 的字典物件, 則你可以使用 list(d.keys()) 取出該字典的 key 集合; 或使用 d['key'] 形式取出 key 對應的 value. 底下為字典物件使用範例 :


或者你可以透過函式 dict() 直接建立 字典物件 :
>>> dict([('sape', 4139), ('guido', 4127), ('john', 4098)])
{'sape': 4139, 'john': 4098, 'guido': 4127}

除此之外, 原本的 list-comp 也可以用在 字典物件 :
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

如果你的 key 是簡單字串, 那你也可以這樣使用 :
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

Looping Techniques :
透過函式 items() 你可以同時對字典物件取得 key 與 value :
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave

如果你想要從 sequence 類型資料同時取得 index 與對應值, 可以使用函式 enumerate() :
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe

如果你想同時檢視多個 sequence 類型的資料, 則可以透過函式 zip() 幫你做到 :


如果你想要反著來讀 sequence 資料, 可以使用函式 reversed() :
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1

如果你希望對 sequence 類型資料排序, 考慮函式 sorted() :


More on Conditions :
你可以使用 in 或 not in 決定某個值或是鍵是否存在串列或是字典物件中 ; 或是使用 is 或 is not 決定某兩個物件是否為同一個. 接著在 if 或 while 比較中, Comparison 可以是連鎖的如 a < b == c則會先比較 a < b 接著比較 b==c. 也就是 (a. 接著你也可以使用 Boolean operators andnot 與 or. 其中 not 有最高優先權, or 最低. 所以 A and not B or C 等同 (A and (not B)) or C. 建議加括號讓結果如你預期. 接著在使用 and 或 or 會有所謂的 short-circuit 效應, 務必注意. 參考範例如下 :
>>> string1, string2, string3 = '', 'John', 'Peter'
>>> non_null = string1 or string2 or string3 # '' means false.
>>> non_null # Because of shot-cut, string3 won't be assigned to non_null
'John'

Comparing Sequences and Other Types :
那麼串列或是 sequence 類型資料有辦法比較嗎? 答案是可以, 不管什麼物件只要它實作對應的 comparison method, 就可以使用 >< 來比較它們. 底下是串列比較範例 :
(1, 2, 3) < (1, 2, 4# 因為 item3 : 3<4
[1, 2, 3] < [1, 2, 4# 因為 item3 : 3<4
'ABC' < 'C' < 'Pascal' < 'Python' # 因為 'A' < 'C' , 'C' < 'P', 'a' < 'y'
(1, 2, 3, 4) < (1, 2, 4# 因為 item3 : 3<4
(1, 2) < (1, 2, -1# 因為 串列 右邊元素多
(1, 2, 3) == (1.0, 2.0, 3.0) # 值相等
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4) # 因為 'aa' < 'abc'

底下為比較物件如果為不同類型時的比較說明 :
Note that comparing objects of different types with < or > is legal provided that the objects have appropriate comparison methods. For example, mixed numeric types are compared according to their numeric value, so 0 equals 0.0, etc. Otherwise, rather than providing an arbitrary ordering, the interpreter will raise aTypeError exception.
This message was edited 52 times. Last update was at 07/01/2012 18:39:24

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!