翻譯:《實(shí)用的Python編程》02_01_Datatypes
目錄 | 上一節(jié) (1.7 函數(shù)) | 下一節(jié) (2.2 容器)
2.1 數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)
本節(jié)以元組和字典為代表介紹數(shù)據(jù)結(jié)構(gòu)。
原始數(shù)據(jù)類型
Python 有一些原始數(shù)據(jù)類型:
- 整數(shù)
- 浮點(diǎn)數(shù)
- 字符串(文本)
空類型
email_address = None
None 常用作可選值或缺失值的占位符。它在條件語句中計(jì)算為 False。
if email_address:
send_email(email_address, msg)
數(shù)據(jù)結(jié)構(gòu)
實(shí)際的程序具有更復(fù)雜的數(shù)據(jù)。例如,關(guān)于股票的持有信息:
100 shares of GOOG at $490.10
這是一個(gè)包含三個(gè)部分的“對(duì)象”:
- 股票的名稱或符號(hào)("GOOG",字符串)
- 股份數(shù)目(100,整數(shù))
- 價(jià)格(490.10,浮點(diǎn)數(shù))
元組
元組是分組在一起的值的集合。
示例:
s = ('GOOG', 100, 490.1)
有時(shí)候會(huì)在語法上省略 () 。
s = 'GOOG', 100, 490.1
特殊情況(0 元組,1 元組)。
t = () # An empty tuple
w = ('GOOG', ) # A 1-item tuple
元組一般用來表示簡(jiǎn)單的記錄或結(jié)構(gòu)。
通常,它是由多個(gè)部分組成的單個(gè)對(duì)象。這有一個(gè)很好的類比:元組就像數(shù)據(jù)庫表中的一行。
元組的內(nèi)容是有序的(類似于數(shù)組)。
s = ('GOOG', 100, 490.1)
name = s[0] # 'GOOG'
shares = s[1] # 100
price = s[2] # 490.1
但是,元組的內(nèi)容無法修改。
>>> s[1] = 75
TypeError: object does not support item assignment
你可以基于當(dāng)前元組創(chuàng)建一個(gè)新元組。
s = (s[0], 75, s[2])
元組打包
元組更多的是把相關(guān)的項(xiàng)打包到一個(gè)實(shí)體(entity)中。
s = ('GOOG', 100, 490.1)
然后,該元組很容易作為單個(gè)對(duì)象傳遞給程序的其它部分。
元組拆包
要在其它地方使用元組,可以把元組的各部分拆包為變量。
name, shares, price = s
print('Cost', shares * price)
左側(cè)變量的數(shù)目必須與元組的結(jié)構(gòu)匹配。
name, shares = s # ERROR
Traceback (most recent call last):
...
ValueError: too many values to unpack
元組與列表
元組看起來像只讀列表。但是,元組最常用于由多個(gè)部分組成的單項(xiàng)。列表通常是類型相同的項(xiàng)的集合,
record = ('GOOG', 100, 490.1) # A tuple representing a record in a portfolio
symbols = [ 'GOOG', 'AAPL', 'IBM' ] # A List representing three stock symbols
字典
字典是鍵到值的映射。有時(shí),字典也稱為哈希表(hash table)或關(guān)聯(lián)數(shù)組(associative array)。鍵用作訪問值的索引。
s = {
'name': 'GOOG',
'shares': 100,
'price': 490.1
}
常見操作
要從字典中獲取值,請(qǐng)使用鍵名。
>>> print(s['name'], s['shares'])
GOOG 100
>>> s['price']
490.10
>>>
要添加或修改值,請(qǐng)使用鍵名進(jìn)行分配。
>>> s['shares'] = 75
>>> s['date'] = '6/6/2007'
>>>
要?jiǎng)h除值,請(qǐng)使用 del 語句。
>>> del s['date']
>>>
為什么使用字典?
當(dāng)存在很多不同的值并且可能會(huì)修改或操作這些值時(shí),字典很有用。字典使代碼更具可讀性。
s['price']
# vs
s[2]
練習(xí)
在上次的幾個(gè)練習(xí)中,編寫了一個(gè)取數(shù)據(jù)文件 Data/portfolio.csv 的程序 。使用 csv 模塊,可以輕松地逐行讀取文件。
>>> import csv
>>> f = open('Data/portfolio.csv')
>>> rows = csv.reader(f)
>>> next(rows)
['name', 'shares', 'price']
>>> row = next(rows)
>>> row
['AA', '100', '32.20']
>>>
盡管讀取文件很容易,但是與讀取數(shù)據(jù)相比,通常使用數(shù)據(jù)做更多的事情。例如,也許想存儲(chǔ)它并對(duì)其執(zhí)行一些計(jì)算。不幸的是,原始的數(shù)據(jù)“行”并不能這樣做。例如,即使是簡(jiǎn)單的數(shù)學(xué)計(jì)算也不行。
>>> row = ['AA', '100', '32.20']
>>> cost = row[1] * row[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
>>>
要執(zhí)行更多的操作,通常需要以某種方式解釋原始數(shù)據(jù),并將其轉(zhuǎn)換為更有用的對(duì)象類型,以便以后處理。有兩種簡(jiǎn)單的方式可以選擇:元組或者字典。
練習(xí) 2.1:元組
在交互式提示符下,創(chuàng)建以下代表上一行的元組,但數(shù)字列要轉(zhuǎn)換為恰當(dāng)?shù)臄?shù)字。
>>> t = (row[0], int(row[1]), float(row[2]))
>>> t
('AA', 100, 32.2)
>>>
使用這種方式,現(xiàn)在可以使用股份數(shù)目乘以價(jià)格來計(jì)算總價(jià),
>>> cost = t[1] * t[2]
>>> cost
3220.0000000000005
>>>
在 Python 中,數(shù)學(xué)沒用了嗎?結(jié)果為什么是 3220.0000000000005?
這是計(jì)算機(jī)上浮點(diǎn)硬件的產(chǎn)物,只能在二進(jìn)制(而不是十進(jìn)制)中準(zhǔn)確表示小數(shù)。即使是涉及十進(jìn)制小數(shù)的簡(jiǎn)單計(jì)算,也會(huì)引入小的誤差。這很正常,如果你之前沒有見過,可能會(huì)有點(diǎn)驚訝。
雖然在所有使用浮點(diǎn)小數(shù)的編程語言中都會(huì)發(fā)生這種情況,但是打印的時(shí)候可以把它隱藏,例如:
>>> print(f'{cost:0.2f}')
3220.00
>>>
元組是只讀的。可以通過嘗試把股份數(shù)目改為 75 來驗(yàn)證這點(diǎn)。
>>> t[1] = 75
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>
盡管無法更改元組的內(nèi)容,但是始終可以創(chuàng)建一個(gè)全新的元組來替換舊的元組。
>>> t = (t[0], 75, t[2])
>>> t
('AA', 75, 32.2)
>>>
每當(dāng)像這樣重新分配現(xiàn)有變量名時(shí),舊值就會(huì)被丟棄。雖然上面的賦值可能看起來像在修改元組,但實(shí)際上是在創(chuàng)建一個(gè)新的元組,并且將舊的元組丟棄。
元組通常用于將值打包或拆包到變量中。請(qǐng)嘗試以下操作:
>>> name, shares, price = t
>>> name
'AA'
>>> shares
75
>>> price
32.2
>>>
取上面的變量并將其打包回元組中:
>>> t = (name, 2*shares, price)
>>> t
('AA', 150, 32.2)
>>>
練習(xí) 2.2:把字典當(dāng)作數(shù)據(jù)結(jié)構(gòu)
可以創(chuàng)建字典來替代元組。
>>> d = {
'name' : row[0],
'shares' : int(row[1]),
'price' : float(row[2])
}
>>> d
{'name': 'AA', 'shares': 100, 'price': 32.2 }
>>>
計(jì)算持有的總價(jià):
>>> cost = d['shares'] * d['price']
>>> cost
3220.0000000000005
>>>
將此示例與上面涉及元組的相同的計(jì)算進(jìn)行比較,將股份數(shù)目修改為 75。
>>> d['shares'] = 75
>>> d
{'name': 'AA', 'shares': 75, 'price': 32.2 }
>>>
與元組不同,字典可以自由修改。添加一些屬性:
>>> d['date'] = (6, 11, 2007)
>>> d['account'] = 12345
>>> d
{'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007), 'account': 12345}
>>>
練習(xí) 2.3: 字典的其它操作
如果將一個(gè)字典轉(zhuǎn)換為列表,則將獲得其所有的鍵:
>>> list(d)
['name', 'shares', 'price', 'date', 'account']
>>>
類似地,如果使用 for 語句對(duì)字典進(jìn)行迭代,則將獲得其所有的鍵。
>>> for k in d:
print('k =', k)
k = name
k = shares
k = price
k = date
k = account
>>>
嘗試使用這個(gè)同時(shí)執(zhí)行查找的變體:
>>> for k in d:
print(k, '=', d[k])
name = AA
shares = 75
price = 32.2
date = (6, 11, 2007)
account = 12345
>>>
也可以使用 keys() 方法獲得所有的鍵:
>>> keys = d.keys()
>>> keys
dict_keys(['name', 'shares', 'price', 'date', 'account'])
>>>
在這里,keys() 稍微有點(diǎn)不同,它返回的是一個(gè) dict_keys 對(duì)象。
這是對(duì)原始字典的覆蓋,它始終提供當(dāng)前字典的鍵——即使字典改變了。例如,試試一下操作:
>>> del d['account']
>>> keys
dict_keys(['name', 'shares', 'price', 'date'])
>>>
請(qǐng)注意,盡管沒有再次調(diào)用 d.keys() ,但鍵'account' 消失了。
一個(gè)更優(yōu)雅地一起使用鍵和值的方式是使用 items() 方法。這可以獲得鍵值組成的元組 (key, value)。
>>> items = d.items()
>>> items
dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
>>> for k, v in d.items():
print(k, '=', v)
name = AA
shares = 75
price = 32.2
date = (6, 11, 2007)
>>>
如果有類似于 items 的元組,那么可以使用 dict() 函數(shù)創(chuàng)建一個(gè)字典。請(qǐng)嘗試以下操作:
>>> items
dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
>>> d = dict(items)
>>> d
{'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007)}
>>>
浙公網(wǎng)安備 33010602011771號(hào)