Counter
計數,以下的例子,找出列表中元素的重復次數:
from collections import Counter
device_temperatures = [13.5, 14.0, 14.0, 14.5, 14.5, 14.5, 15.0, 16.0]
temperature_counter = Counter(device_temperatures)
# Counter({14.5: 3, 14.0: 2, 13.5: 1, 15.0: 1, 16.0: 1})
print(temperature_counter)
print(type(temperature_counter)) # <class 'collections.Counter'>
print(temperature_counter[13.5]) # 1
print(temperature_counter[14.0]) # 2
print(temperature_counter[14.5]) # 3
print(temperature_counter[15.0]) # 1
print(temperature_counter[16.0]) # 1
defaultdict
如下的代碼將產生錯誤 KeyError
,因為 my_dict
裡沒有為 'hi'
的 key:
my_dict={
'hello':5}
print(my_dict['hi'])
# Traceback (most recent call last):
# File "<string>", line 4, in <module>
# KeyError: 'hi'
# >
與之相反, defaultdict
從不會引發 KeyError
。
以下是一個由 tuple 組成的列表 coworkers
,列出了每個人就讀過的學校:
coworkers = [('Rolf', 'MIT'), ('Jen', 'Oxford'), ('Rolf', 'Cambridge'), ('Charlie', 'Manchester')]
現在要得到一個dictionary:
{
'Rolf': ['MIT', 'Cmbridge'],
'Jen': ['Oxford'],
'Charlie': ['Manchester']
}
一般的寫法:
coworkers = [('Rolf', 'MIT'), ('Jen', 'Oxford'), ('Rolf', 'Cambridge'), ('Charlie', 'Manchester')]
alma_maters = {
} # (alma mater:母校)
for coworker in coworkers:
if coworker[0] not in alma_maters:
alma_maters[coworker[0]] = []
alma_maters[coworker[0]].append(coworker[1])
或者:
coworkers = [('Rolf', 'MIT'), ('Jen', 'Oxford'), ('Rolf', 'Cambridge'), ('Charlie', 'Manchester')]
alma_maters = {
} # (alma mater:母校)
for coworker, place in coworkers:
if coworker not in alma_maters:
alma_maters[coworker] = [] # default value
alma_maters[coworker].append(place)
print(alma_maters)
改為使用 defaultdict
:
from collections import defaultdict
coworkers = [('Rolf', 'MIT'), ('Jen', 'Oxford'), ('Rolf', 'Cambridge'), ('Charlie', 'Manchester')]
# 如果詞典中的某一個key不存在,則調用參數裡的function
# 這裡 function 是 list,即調用list,得到一個空的列表 []
alma_maters = defaultdict(list)
for coworker, place in coworkers:
alma_maters[coworker].append(place)
# 如果希望在訪問不存在的 key 時,能引發異常, 則添加下面的一行
# alma_maters.default_factory = None
# (None 改成 int 時生成 0 值)
print(alma_maters['Rolf']) # ['MIT', 'Cambridge']
print(alma_maters['Jen']) # ['Oxford']
print(alma_maters['Charlie']) # ['Manchester']
print(alma_maters['Anne']) # []
from collections import defaultdict
my_company = 'Teclado'
coworkers = ['Jen', 'Li', 'Charlie', 'Rhys']
other_coworkers = [('Rolf', 'Apple Inc.'), ('Anna', 'Google')]
# 不能直接寫 my_company, 因為 defaultdict 接受函數為參數
# lambda: my_company 返回 my_company
coworker_companies = defaultdict(lambda: my_company)
for person, company in other_coworkers:
coworker_companies[person] = company
# coworkers[1] 是 'Li', 輸出默認值 Teclado
print(coworker_companies[coworkers[1]])
# other_coworkers[0][0] 是 'Rolf', 輸出 Apple Inc.
print(coworker_companies[other_coworkers[0][0]])
OrderedDict
這裡是 Pascal Case
顧名思義,OrderedDict 是有序詞典,是指鍵值對的順序按插入順序排序。
from collections import OrderedDict
o = OrderedDict()
o['Rolf'] = 6
o['Jose'] = 10
o['Jen'] = 3
# keys are always in the order in which they were inserted
# OrderedDict([('Rolf', 6), ('Jose', 10), ('Jen', 3)])
print(o)
o.move_to_end('Rolf') # 移到末尾
# OrderedDict([('Jose', 10), ('Jen', 3), ('Rolf', 6)])
print(o)
o.move_to_end('Rolf', last = False) # 移到反向的末尾,即開頭
# OrderedDict([('Rolf', 6), ('Jose', 10), ('Jen', 3)])
print(o)
o.popitem()
# OrderedDict([('Rolf', 6), ('Jose', 10)])
print(o)
o.popitem(False)
: 刪除開頭的元素
但從 Python 3.7 開始,dictionary 已經按插入排序,所以 OrderedDict
用處不是特別大。
Are dictionaries ordered in Python 3.6+?
namedtuple
namedtuple
: 給 tuple 以及 tuple 中的每一個元素都取名字
如下的代碼,account[0]
,account[1]
分別指的什麼不是顯而易見:
account = ('checking', 1850.90)
print(account[0]) # name
print(account[1]) # balance
使用 namedtuple
:
from collections import namedtuple
account = ('checking', 1850.90)
# 第1個參數是 tuple 名稱,和定義名稱相同
# 第2個參數是 fields 名稱
Account = namedtuple("Account", ['name', 'balance'])
accountNamedTuple_1 = Account('checking', 1850.90)
print(accountNamedTuple_1.name, accountNamedTuple_1.balance) # checking 1850.9
accountNamedTuple_2 = Account._make(account)
account_name_2, account_balance_2 = accountNamedTuple_2
print(account_name_2, account_balance_2) # checking 1850.9
accountNamedTuple_3 = Account(*account)
account_name_3, account_balance_3 = accountNamedTuple_3
print(account_name_3, account_balance_3) # checking 1850.9
print(accountNamedTuple_1._asdict()['balance']) # 1850.9
print(accountNamedTuple_2._asdict()['balance']) # 1850.9
print(accountNamedTuple_3._asdict()['balance']) # 1850.9
從 csv 文件或者 database 讀取數據時,使用 namedtuple
可使代碼更容易理解。
deque
deque
:double ended queue 雙端隊列,使用deque
而非 list
的原因首先是deque
效率高,其次它保證線程安全 (thread safe),deque
所有的操作都是線程安全的 ,因此在使用 thread 時可使用 deque
。
from collections import deque
friends = deque(('Rolf', 'Charlie', 'Jen', 'Anna'))
friends.append('Jose')
friends.appendleft('Anthony')
print(friends) # deque(['Anthony', 'Rolf', 'Charlie', 'Jen', 'Anna', 'Jose'])
friends.pop()
print(friends) # deque(['Anthony', 'Rolf', 'Charlie', 'Jen', 'Anna'])
friends.popleft()
print(friends) # deque(['Rolf', 'Charlie', 'Jen', 'Anna'])