翻譯:《實用的Python編程》02_01_Datatypes

目錄 | 上一節 (1.7 函數) | 下一節 (2.2 容器)python

2.1 數據類型和數據結構

本節以元組和字典爲表明介紹數據結構。git

原始數據類型

Python 有一些原始數據類型:github

  • 整數
  • 浮點數
  • 字符串(文本)

空類型

email_address = None

None 經常使用做可選值或缺失值的佔位符。它在條件語句中計算爲 False數據庫

if email_address:
    send_email(email_address, msg)

數據結構

實際的程序具備更復雜的數據。例如,關於股票的持有信息:編程

100 shares of GOOG at $490.10

這是一個包含三個部分的「對象」:segmentfault

  • 股票的名稱或符號("GOOG",字符串)
  • 股份數目(100,整數)
  • 價格(490.10,浮點數)

元組

元組是分組在一塊兒的值的集合。數組

示例:數據結構

s = ('GOOG', 100, 490.1)

有時候會在語法上省略 ()編程語言

s = 'GOOG', 100, 490.1

特殊狀況(0 元組,1 元組)。函數

t = ()            # An empty tuple
w = ('GOOG', )    # A 1-item tuple

元組通常用來表示簡單的記錄或結構。

一般,它是由多個部分組成的單個對象。這有一個很好的類比:元組就像數據庫表中的一行。

元組的內容是有序的(相似於數組)。

s = ('GOOG', 100, 490.1)
name = s[0]                 # 'GOOG'
shares = s[1]               # 100
price = s[2]                # 490.1

可是,元組的內容沒法修改。

>>> s[1] = 75
TypeError: object does not support item assignment

你能夠基於當前元組建立一個新元組。

s = (s[0], 75, s[2])

元組打包

元組更多的是把相關的項打包到一個實體(entity)中。

s = ('GOOG', 100, 490.1)

而後,該元組很容易做爲單個對象傳遞給程序的其它部分。

元組拆包

要在其它地方使用元組,能夠把元組的各部分拆包爲變量。

name, shares, price = s
print('Cost', shares * price)

左側變量的數目必須與元組的結構匹配。

name, shares = s     # ERROR
Traceback (most recent call last):
...
ValueError: too many values to unpack

元組與列表

元組看起來像只讀列表。可是,元組最經常使用於由多個部分組成的單項。列表一般是類型相同的項的集合,

record = ('GOOG', 100, 490.1)       # A tuple representing a record in a portfolio

symbols = [ 'GOOG', 'AAPL', 'IBM' ]  # A List representing three stock symbols

字典

字典是鍵到值的映射。有時,字典也稱爲哈希表(hash table)或關聯數組(associative array)。鍵用做訪問值的索引。

s = {
    'name': 'GOOG',
    'shares': 100,
    'price': 490.1
}

常見操做

要從字典中獲取值,請使用鍵名。

>>> print(s['name'], s['shares'])
GOOG 100
>>> s['price']
490.10
>>>

要添加或修改值,請使用鍵名進行分配。

>>> s['shares'] = 75
>>> s['date'] = '6/6/2007'
>>>

要刪除值,請使用 del 語句。

>>> del s['date']
>>>

爲何使用字典?

當存在不少不一樣的值而且可能會修改或操做這些值時,字典頗有用。字典使代碼更具可讀性。

s['price']
# vs
s[2]

練習

在上次的幾個練習中,編寫了一個取數據文件 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']
>>>

儘管讀取文件很容易,可是與讀取數據相比,一般使用數據作更多的事情。例如,也許想存儲它並對其執行一些計算。不幸的是,原始的數據「行」並不能這樣作。例如,即便是簡單的數學計算也不行。

>>> 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'
>>>

要執行更多的操做,一般須要以某種方式解釋原始數據,並將其轉換爲更有用的對象類型,以便之後處理。有兩種簡單的方式能夠選擇:元組或者字典。

練習 2.1:元組

在交互式提示符下,建立如下表明上一行的元組,但數字列要轉換爲恰當的數字。

>>> t = (row[0], int(row[1]), float(row[2]))
>>> t
('AA', 100, 32.2)
>>>

使用這種方式,如今可使用股份數目乘以價格來計算總價,

>>> cost = t[1] * t[2]
>>> cost
3220.0000000000005
>>>

在 Python 中,數學沒用了嗎?結果爲何是 3220.0000000000005?

這是計算機上浮點硬件的產物,只能在二進制(而不是十進制)中準確表示小數。即便是涉及十進制小數的簡單計算,也會引入小的偏差。這很正常,若是你以前沒有見過,可能會有點驚訝。

雖然在全部使用浮點小數的編程語言中都會發生這種狀況,可是打印的時候能夠把它隱藏,例如:

>>> print(f'{cost:0.2f}')
3220.00
>>>

元組是隻讀的。能夠經過嘗試把股份數目改成 75 來驗證這點。

>>> t[1] = 75
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>

儘管沒法更改元組的內容,可是始終能夠建立一個全新的元組來替換舊的元組。

>>> t = (t[0], 75, t[2])
>>> t
('AA', 75, 32.2)
>>>

每當像這樣從新分配現有變量名時,舊值就會被丟棄。雖然上面的賦值可能看起來像在修改元組,但其實是在建立一個新的元組,而且將舊的元組丟棄。

元組一般用於將值打包或拆包到變量中。請嘗試如下操做:

>>> name, shares, price = t
>>> name
'AA'
>>> shares
75
>>> price
32.2
>>>

取上面的變量並將其打包回元組中:

>>> t = (name, 2*shares, price)
>>> t
('AA', 150, 32.2)
>>>

練習 2.2:把字典看成數據結構

能夠建立字典來替代元組。

>>> d = {
        'name' : row[0],
        'shares' : int(row[1]),
        'price'  : float(row[2])
    }
>>> d
{'name': 'AA', 'shares': 100, 'price': 32.2 }
>>>

計算持有的總價:

>>> cost = d['shares'] * d['price']
>>> cost
3220.0000000000005
>>>

將此示例與上面涉及元組的相同的計算進行比較,將股份數目修改成 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}
>>>

練習 2.3: 字典的其它操做

若是將一個字典轉換爲列表,則將得到其全部的鍵:

>>> list(d)
['name', 'shares', 'price', 'date', 'account']
>>>

相似地,若是使用 for 語句對字典進行迭代,則將得到其全部的鍵。

>>> for k in d:
        print('k =', k)

k = name
k = shares
k = price
k = date
k = account
>>>

嘗試使用這個同時執行查找的變體:

>>> 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() 稍微有點不一樣,它返回的是一個 dict_keys 對象。

這是對原始字典的覆蓋,它始終提供當前字典的鍵——即便字典改變了。例如,試試一下操做:

>>> del d['account']
>>> keys
dict_keys(['name', 'shares', 'price', 'date'])
>>>

請注意,儘管沒有再次調用 d.keys() ,但鍵'account' 消失了。

一個更優雅地一塊兒使用鍵和值的方式是使用 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() 函數建立一個字典。請嘗試如下操做:

>>> 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)}
>>>

目錄 | 上一節 (1.7 函數) | 下一節 (2.2 容器)

注:完整翻譯見 https://github.com/codists/practical-python-zh

相關文章
相關標籤/搜索