Python可以這樣玩(4):元組字典與集合

元組與生成器推導式

元組也是 Python 一種重要的序列結構,從形式而言,元組的所有元素放在一對小括號中,元素之間以逗號分隔。如下:

>>> x = (1,2,3)
>>> x
(1, 2, 3)
>>> type(x)
<class 'tuple'>
>>> x = (3)
>>> x
3
>>> type(x)
<class 'int'>
>>> x = (3,)
>>> x
(3,)
>>> type(x)
<class 'tuple'>
>>> x = ()
>>> x
()
>>> tuple(range(5))
(0, 1, 2, 3, 4)
>>> 

元組屬於不可變序列,與列表不同。而Python 對原組做了大量最佳化,因此,存取和處理的速度比列表更快。

另外,作為不可變序列,元組與整數、字串一樣,可以當成字典的鍵,有關字典的部分,我們後面說明。

雖然元組是不可變序列,但是如果其內部包含了可變序列,情況就複雜了:

>>> x = ([1,2],3)
>>> x[0][0] = 5
>>> x
([5, 2], 3)
>>> 

元組的生成器推導式與列表推導式非常類似,主要的差異在於,生成器推導式的結果是一個生成器物件,而非元組。不像列表推導式生成的就是列表。生成器物件可以依照我們的需求產生元組或是列表,還有一個特性就是生成器推導式會用 __next__() 方法來巡訪元素,而且當巡訪結束之後,就巡訪不到元素了。請看下面的範例:

>>> g = ((i + 2)**2 for i in range(10))
>>> g
<generator object <genexpr> at 0x00000223B390E200>
>>> tuple(g)
(4, 9, 16, 25, 36, 49, 64, 81, 100, 121)
>>> list(g)
[]
>>> g = ((i + 2)**2 for i in range(10))
>>> list(g)
[4, 9, 16, 25, 36, 49, 64, 81, 100, 121]
>>> tuple(g)
()
>>> g = ((i + 2)**2 for i in range(10))
>>> g.__next__()
4
>>> g.__next__()
9
>>> 


字典

字典(dictionary) 是包含若干 :元素的無序可變序列,為何叫做字典,顧名思義就是可以透過鍵來查值,如同查字典,下面的例子一看應該就明白:

>>> mydict = {'apple':'蘋果', 'bear':'', 'cat':''}
>>> mydict
{'apple': '蘋果', 'bear': '', 'cat': ''}
>>> mydict['apple']
'蘋果'
>>> mydict['蘋果']
Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    mydict['蘋果']
KeyError: '蘋果'
>>>  

字典的建立,元素的增加、修改與刪除

除了上面的方法,我們可以使用 dict() zip()來建立字典:

>>> keys = [1,2,3,4]
>>> value = ['a','b','c','d']
>>> mydict = dict(zip(keys,value))
>>> mydict
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
>>> mylist = list(zip(keys,value))
>>> mylist
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
>>> print(mydict)
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
>>> d = dict(name='Wang', age=18)
>>> d
{'name': 'Wang', 'age': 18}
>>> d = dict.fromkeys(['name','age','sex'])    #建立空字典
>>> d
{'name': None, 'age': None, 'sex': None}
>>> 

如同列表一樣,字典可以透過 mydict[‘’]=’的方式來改變字典元素的值,我們還可以用 update() 方法,將另一個字典的 :一次性的加到目前的字典物件,我們接續上面的例子:

>>> d
{'name': None, 'age': None, 'sex': None}
>>> d['name']='Wang'
>>> e = {'name':'Andrew','age':20, 'phone':'0922332333'}
>>> d
{'name': 'Wang', 'age': None, 'sex': None}
>>> e
{'name': 'Andrew', 'age': 20, 'phone': '0922332333'}
>>> d.update(e)
>>> d
{'name': 'Andrew', 'age': 20, 'sex': None, 'phone': '0922332333'}
>>> 

也可以新增和刪除字典元素,並在字典裏面加入列表元素:

>>> d
{'name': 'Elvis', 'age': 20, 'sex': None, 'phone': '0922332333'}
>>> d['score'] = [ 92, 94, 86 ]
>>> d
{'name': 'Elvis', 'age': 20, 'sex': None, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> del d['sex']
>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> 

隨堂測驗 建立一個字典的列表

看了上面的例子是否感覺可以利用在線上遊戲隊員基本資料以及分數上面
d 字典當成一個隊員,裡面有姓名、年齡、電話、以及三次比賽成績
如果團隊裡面有五個隊員該如何做呢?

>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> team = [d]
>>> team
[{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}]
>>> e = {'name': 'Zoe', 'age': 30, 'phone': '0911331331', 'score': [91, 74, 76]}
>>> team.append(e)
>>> team
[{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}, {'name': 'Zoe', 'age': 30, 'phone': '0911331331', 'score': [91, 74, 76]}]
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 

我們可以透過 d[‘name’]的方式讀取元素的值,但是如果該鍵不存在,則會拋出錯誤:

>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> d['name']
'Elvis'
>>> d['address']
Traceback (most recent call last):
  File "<pyshell#121>", line 1, in <module>
    d['address']
KeyError: 'address'
>>> 

當有錯誤拋出的時候,就代表程式被中斷了,所以如果我們是在寫程式,當然不希望程式因為錯誤而跳出,這時候我們就必須用下面的技巧來處理:

>>> if 'Address' in d:
    print(d['Address'])
else:
    print('不存在')
   
不存在
>>> try:
    print(d['Address'])
except:
    print('不存在')
   
不存在
>>> 

雖然上面的方法可以滿足要求,但是程式碼很長,我們可以利用 get() 方法來達成同樣的結果:

>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86]}
>>> d.get('name','Not Exist')
'Elvis'
>>> d.get('address','Not Exist')
'Not Exist'
>>> 

另外還有一種方式,就是如果該鍵不存在的時候,就新增該鍵,並加入一個預設值:

>>> d.setdefault('name','XXX')
'Elvis'
>>> d.setdefault('address','XXX')
'XXX'
>>> d
{'name': 'Elvis', 'age': 20, 'phone': '0922332333', 'score': [92, 94, 86], 'address': 'XXX'}
>>> 

最後,對字典做反覆運算時,預設是巡訪字典的鍵,當然,我們可以使用 item()方法同時巡訪 :值;keys() 方法返回所有鍵,value() 方法返回所有值。

>>> e
{'name': 'Zoe', 'age': 30, 'phone': '0911331331', 'score': [91, 74, 76]}
>>> for item in e:
    print(item)
   
name
age
phone
score
>>> for item in e.items():
    print(item)
   
('name', 'Zoe')
('age', 30)
('phone', '0911331331')
('score', [91, 74, 76])
>>> e.keys()
dict_keys(['name', 'age', 'phone', 'score'])
>>> e.values()
dict_values(['Zoe', 30, '0911331331', [91, 74, 76]])
>>> 

集合

集合是無序可變序列,使用一對大括號作為符號,元素之間以逗點分隔,同一個集合內的每個元素不可以重複,跟數學上的集合是相同的。

前面的章節已經介紹過集合的基本運算:聯集、交集、差集、對稱差集。 

集合的操作和運算

使用 add() 方法來增加新元素,使用 update() 方法來合併另一個集合到目前集合中:

>>> s = {1,2,3}
>>> s.add(3)
>>> s
{1, 2, 3}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.update({4,5})
>>> s
{1, 2, 3, 4, 5}
>>> 

集合物件 pop() 方法會隨機刪除一個元素並返回該元素,如果集合為空集合則拋出異常;remove() 方法是刪除集合中的元素,如果元素不存在會拋出異常;discard() 會從集合中刪除一特定元素,如果不存在則忽略此操作;clear() 方法刪除所有元素:

>>> s
{1, 2, 3, 4, 5}
>>> s.discard(6)
>>> s
{1, 2, 3, 4, 5}
>>> s.remove(6)
Traceback (most recent call last):
  File "<pyshell#175>", line 1, in <module>
    s.remove(6)
KeyError: 6
>>> s.remove(5)
>>> s
{1, 2, 3, 4}
>>> s.pop()
1
>>> s
{2, 3, 4}
>>> s.clear()
>>> s
set()
>>> s.pop()
Traceback (most recent call last):
  File "<pyshell#182>", line 1, in <module>
    s.pop()
KeyError: 'pop from an empty set'
>>>  

序列拆解

這功能其實跟 Python 的語言特性有關,一般程式語言的 = 只能一對一,但是 Python 可以多對多,請自行參考下面的範例,如果有疑問,可以直接發問:

>>> x = 1
>>> x , y = 1, 2
>>> x
1
>>> y
2
>>> x, y, z = range(3)
>>> x
0
>>> y
1
>>> z
2
>>> a = [4,5,6]
>>> b, c, d = a
>>> b
4
>>> c
5
>>> d
6
>>> 

留言

這個網誌中的熱門文章

Python可以這樣玩(16):共陰/共陽七段顯示器

Python可以這樣玩(15):蜂鳴器與音樂

Python可以這樣玩(13):外部LED控制