當前位置: 首頁 ? 深入 Python 3 ?
難度級別: ?????
? Wonder is the foundation of all philosophy, inquiry its progress, ignorance its end. ?
— Michel de Montaigne
讓我們暫時將 第一份 Python 程序 拋在腦后,來聊一聊數據類型。在 Python 中, 每個值都有一種數據類型,但您并不需要聲明變量的數據類型。那該方式是如何運作的呢?Python 根據每個變量的初始賦值情況分析其類型,并在內部對其進行跟蹤。
Python 有多種內置數據類型。以下是比較重要的一些:
True[真] 或為 False[假]。1 和 2)、Floats[浮點數](1.1 和 1.2)、Fractions[分數](1/2 和 2/3);甚至是 Complex Number[復數]。當然,還有更多的類型。在 Python 中一切均為對象,因此存在像 module[模塊]、 function[函數]、 class[類]、 method[方法]、 file[文件] 甚至 compiled code[已編譯代碼] 這樣的類型。您已經見過這樣一些例子:模塊的 name、 函數的 docstrings 等等。將學到的包括 《類 與 迭代器》 中的 Classes[類],以及 《文件》 中的 Files[文件]。
Strings[字符串]和 Bytes[字節串]比較重要,也相對復雜,足以開辟獨立章節予以講述。讓我們先看看其它類型。
?
布爾類型或為真或為假。Python 有兩個被巧妙地命名為 True 和 False 的常量,可用于對布爾類型的直接賦值。表達式也可以計算為布爾類型的值。在某些地方(如 if 語句),Python 所預期的就是一個可計算出布爾類型值的表達式。這些地方稱為 布爾類型上下文環境。事實上,可在布爾類型上下文環境中使用任何表達式,而 Python 將試圖判斷其真值。在布爾類型上下文環境中,不同的數據類型對于何值為真、何值為假有著不同的規則。(看過本章稍后的實例后,這一點將更好理解。)
例如,看看 humansize.py 中的這個片段:
if size < 0:
raise ValueError('number must be non-negative')
size 是整數, 0 是整數,而 < 是數字運算符。size < 0 表達式的結果始終是布爾值。可在 Python 交互式 shell 中自行測試下結果:
>>> size = 1 >>> size < 0 False >>> size = 0 >>> size < 0 False >>> size = -1 >>> size < 0 True
由于 Python 2 的一些遺留問題,布爾值可以當做數值對待。True 為 1;False 為 0 。
>>> True + True 2 >>> True - False 1 >>> True * False 0 >>> True / False Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: int division or modulo by zero
喔,喔,喔!別那么干。忘掉我剛才說的。
?
數值類型是可畏的。有太多類型可選了。Python 同時支持 Integer[整型] 和 Floating Point[浮點型] 數值。無任何類型聲明可用于區分;Python 通過是否有 小數 點來分辨它們。
>>> type(1) ① <class 'int'> >>> isinstance(1, int) ② True >>> 1 + 1 ③ 2 >>> 1 + 1.0 ④ 2.0 >>> type(2.0) <class 'float'>
type() 函數來檢測任何值或變量的類型。正如所料,1 為 int 類型。isinstance() 函數判斷某個值或變量是否為給定某個類型。int 與一個 int 相加將得到一個 int 。int 與一個 float 相加將得到一個 float 。Python 把 int 強制轉換為 float 以進行加法運算;然后返回一個 float 類型的結果。正如剛才所看到的,一些運算符(如:加法)會根據需把整數強制轉換為浮點數。也可自行對其進行強制轉換。
>>> float(2) ① 2.0 >>> int(2.0) ② 2 >>> int(2.5) ③ 2 >>> int(-2.5) ④ -2 >>> 1.12345678901234567890 ⑤ 1.1234567890123457 >>> type(1000000000000000) ⑥ <class 'int'>
float() 函數,可以顯示地將 int 強制轉換為 float。int() 將 float 強制轉換為 int 。int() 將進行取整,而不是四舍五入。int() 函數朝著 0 的方法進行取整。它是個真正的取整(截斷)函數,而不是 floor[地板]函數。?Python 2 對于
int[整型]和long[長整型]采用不同的數據類型。int數據類型受到sys.maxint的限制,因平臺該限制也會有所不同,但通常是232-1。Python 3 只有一種整數類型,其行為方式很有點像 Python 2 的舊long[長整數]類型。參閱 PEP 237 了解更多細節。
對數值可進行各種類型的運算。
>>> 11 / 2 ① 5.5 >>> 11 // 2 ② 5 >>> ?11 // 2 ③ ?6 >>> 11.0 // 2 ④ 5.0 >>> 11 ** 2 ⑤ 121 >>> 11 % 2 ⑥ 1
/ 運算符執行浮點除法。即便分子和分母都是 int,它也返回一個 float 浮點數。// 運算符執行古怪的整數除法。如果結果為正數,可將其視為朝向小數位取整(不是四舍五入),但是要小心這一點。// 運算符將結果朝著最近的整數“向上”四舍五入。從數學角度來說,由于 ?6 比 ?5 要小,它是“向下”四舍五入,如果期望將結果取整為 ?5,它將會誤導你。// 運算符并非總是返回整數結果。如果分子或者分母是 float,它仍將朝著最近的整數進行四舍五入,但實際返回的值將會是 float 類型。** 運算符的意思是“計算冪”,112 結果為 121 。% 運算符給出了進行整除之后的余數。11 除以 2 結果為 5 以及余數 1,因此此處的結果為 1。?在 Python 2 中,運算符
/通常表示整數除法,但是可以通過在代碼中加入特殊指令,使其看起來像浮點除法。在 Python 3 中,/運算符總是表示浮點除法。參閱 PEP 238 了解更多細節。
Python 并不僅僅局限于整數和浮點數類型。它可以完成你在高中階段學過、但幾乎已經全部忘光的所有古怪數學運算。
>>> import fractions ① >>> x = fractions.Fraction(1, 3) ② >>> x Fraction(1, 3) >>> x * 2 ③ Fraction(2, 3) >>> fractions.Fraction(6, 4) ④ Fraction(3, 2) >>> fractions.Fraction(0, 0) ⑤ Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fractions.py", line 96, in __new__ raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(0, 0)
fractions 模塊。Fraction 對象并傳入分子和分母。Fraction 對象。2 * (1/3) = (2/3)
Fraction 對象將會自動進行約分。(6/4) = (3/2)
還可在 Python 中進行基本的三角函數運算。
>>> import math >>> math.pi ① 3.1415926535897931 >>> math.sin(math.pi / 2) ② 1.0 >>> math.tan(math.pi / 4) ③ 0.99999999999999989
math 模塊中有一個代表 π 的常量,表示圓的周長與直徑之比率(圓周率)。math 模塊包括了所有的基本三角函數,包括:sin()、 cos()、tan() 及像 asin() 這樣的變體函數。tan(π / 4) 將返回 1.0,而不是 0.99999999999999989。可以在 if 這樣的 布爾類型上下文環境中 使用數值。零值是 false[假],非零值是 true[真]。
>>> def is_it_true(anything): ① ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(1) ② yes, it's true >>> is_it_true(-1) yes, it's true >>> is_it_true(0) no, it's false >>> is_it_true(0.1) ③ yes, it's true >>> is_it_true(0.0) no, it's false >>> import fractions >>> is_it_true(fractions.Fraction(1, 2)) ④ yes, it's true >>> is_it_true(fractions.Fraction(0, 1)) no, it's false
0.0 為假。請千萬小心這一點!如果有輕微的四舍五入偏差(正如在前面小節中看到的那樣,這并非不可能的事情),那么 Python 將測試 0.0000000000001 而不是 0 ,并將返回一個 True 值。Fraction(0, n) 為假。所有其它分數為真。?
列表是 Python 的主力數據類型。當提到 “列表 ”時,您腦海中可能會閃現“必須進一步聲明大小的數組,只能包含同一類對象“ 等想法。千萬別這么想。列表比那要酷得多。
? Python 中的列表類似 Perl 5 中的數組。在 Perl 5 中,存儲數組的變量總是以字符
@開頭;在 Python 中,變量可隨意命名,Python 僅在內部對數據類型進行跟蹤。
? Python 中的列表更像 Java 中的數組(盡管可以把列表當做生命中所需要的一切來使用)。一個更好的比喻可能是
ArrayList類,該類可以容納任何對象,并可在添加新元素時進行動態拓展。
列表創建非常輕松:使用中括號包裹一系列以逗號分割的值即可。
>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] ① >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[0] ② 'a' >>> a_list[4] ③ 'example' >>> a_list[-1] ④ 'example' >>> a_list[-3] ⑤ 'mpilgrim'
a_list[0] 。a_list[4],因為列表(索引)總是以零為基點的。a_list[-1] 。a_list[-n] == a_list[len(a_list) - n] 。因此在此列表中, a_list[-3] == a_list[5 - 3] == a_list[2]。定義列表后,可從其中獲取任何部分作為新列表。該技術稱為對列表進行 切片 。
>>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[1:3] ① ['b', 'mpilgrim'] >>> a_list[1:-1] ② ['b', 'mpilgrim', 'z'] >>> a_list[0:3] ③ ['a', 'b', 'mpilgrim'] >>> a_list[:3] ④ ['a', 'b', 'mpilgrim'] >>> a_list[3:] ⑤ ['z', 'example'] >>> a_list[:] ⑥ ['a', 'b', 'mpilgrim', 'z', 'example']
a_list[1]),截止但不包含第二個切片索引(本例中的 a_list[3])。a_list[0:3] 返回列表的頭三個元素,從 a_list[0] 開始,截止到但不包括 a_list[3] 。a_list[:3] 與 a_list[0:3] 是完全相同的,因為起點 0 被隱去了。a_list[3:] 與 a_list[3:5] 是完全相同的,因為該列表有五個元素。此處有個好玩的對稱現象。在這個五元素列表中, a_list[:3] 返回頭三個元素,而 a_list[3:] 返回最后兩個元素。事實上,無論列表的長度是多少, a_list[:n] 將返回頭 n 個元素,而 a_list[n:] 返回其余部分。a_list[:] 是對列表進行復制的一條捷徑。有四種方法可用于向列表中增加元素。
>>> a_list = ['a'] >>> a_list = a_list + [2.0, 3] ① >>> a_list ② ['a', 2.0, 3] >>> a_list.append(True) ③ >>> a_list ['a', 2.0, 3, True] >>> a_list.extend(['four', 'Ω']) ④ >>> a_list ['a', 2.0, 3, True, 'four', 'Ω'] >>> a_list.insert(0, 'Ω') ⑤ >>> a_list ['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
+ 運算符連接列表以創建一個新列表。列表可包含任何數量的元素;沒有大小限制(除了可用內存的限制)。然而,如果內存是個問題,那就必須知道在進行連接操作時,將在內存中創建第二個列表。在該情況下,新列表將會立即被賦值給已有變量 a_list 。因此,實際上該行代碼包含兩個步驟 — 連接然后賦值 — 當處理大型列表時,該操作可能(暫時)消耗大量內存。append() 方法向列表的尾部添加一個新的元素。(現在列表中有 四種 不同數據類型!)extend() 方法只接受一個列表作為參數,并將該參數的每個元素都添加到原有的列表中。insert() 方法將單個元素插入到列表中。第一個參數是列表中將被頂離原位的第一個元素的位置索引。列表中的元素并不一定要是唯一的;比如說:現有兩個各自獨立的元素,其值均為 'Ω':,第一個元素 a_list[0] 以及最后一個元素 a_list[6] 。?
a_list.insert(0, value)就像是 Perl 中的unshift()函數。它將一個元素添加到列表的頭部,所有其它的元素都被頂理原先的位置以騰出空間。
讓我們進一步看看 append() 和 extend() 的區別。
>>> a_list = ['a', 'b', 'c'] >>> a_list.extend(['d', 'e', 'f']) ① >>> a_list ['a', 'b', 'c', 'd', 'e', 'f'] >>> len(a_list) ② 6 >>> a_list[-1] 'f' >>> a_list.append(['g', 'h', 'i']) ③ >>> a_list ['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']] >>> len(a_list) ④ 7 >>> a_list[-1] ['g', 'h', 'i']
extend() 方法只接受一個參數,而該參數總是一個列表,并將列表 a_list 中所有的元素都添加到該列表中。append() 方法只接受一個參數,但可以是任何數據類型。在此,對一個 3 元素列表調用 append() 方法。
>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
>>> a_list.count('new') ①
2
>>> 'new' in a_list ②
True
>>> 'c' in a_list
False
>>> a_list.index('mpilgrim') ③
3
>>> a_list.index('new') ④
2
>>> a_list.index('c') ⑤
Traceback (innermost last):
File "<interactive input>", line 1, in ?ValueError: list.index(x): x not in list
count() 方法返回了列表中某個特定值出現的次數。in 運算符將會比使用 count() 方法要略快一些。in 運算符總是返回 True 或 False;它不會告訴你該值出現在什么位置。index() 方法。盡管可以通過第二個參數(以 0 為基點的)索引值來指定起點,通過第三個參數(以 0 基點的)索引來指定搜索終點,但缺省情況下它將搜索整個列表,index() 方法將查找某值在列表中的第一次出現。在該情況下,'new' 在列表中出現了兩次,分別為 a_list[2] 和 a_list[4],但 index() 方法將只返回第一次出現的位置索引值。index() 方法將會引發一個例外。等等,什么?是這樣的:如果沒有在列表中找到該值, index() 方法將會引發一個例外。這是 Python 語言最顯著不同之處,其它多數語言將會返回一些無效的索引值(像是 -1)。當然,一開始這一點看起來比較討厭,但我想您會逐漸欣賞它。這意味著您的程序將會在問題的源頭處崩潰,而不是之后奇怪地、默默地崩潰。請記住, -1 是合法的列表索引值。如果 index() 方法返回 -1,可能會導致調整過程變得不那么有趣!
列表可以自動拓展或者收縮。您已經看到了拓展部分。也有幾種方法可從列表中刪除元素。
>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'b' >>> del a_list[1] ① >>> a_list ['a', 'new', 'mpilgrim', 'new'] >>> a_list[1] ② 'new'
del 語句從列表中刪除某個特定元素。1 之后再訪問索引 1 將 不會 導致錯誤。被刪除元素之后的所有元素將移動它們的位置以“填補”被刪除元素所產生的“縫隙”。不知道位置索引?這不成問題,您可以通過值而不是索引刪除元素。
>>> a_list.remove('new') ①
>>> a_list
['a', 'mpilgrim', 'new']
>>> a_list.remove('new') ②
>>> a_list
['a', 'mpilgrim']
>>> a_list.remove('new')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
remove() 方法從列表中刪除某個元素。remove() 方法接受一個 value 參數,并刪除列表中該值的第一次出現。同樣,被刪除元素之后的所有元素將會將索引位置下移,以“填補縫隙”。列表永遠不會有“縫隙”。remove() 方法,但如果試圖刪除列表中不存在的元素,它將引發一個例外。另一有趣的列表方法是 pop() 。pop() 方法是從列表刪除元素的另一方法,但有點變化。
>>> a_list = ['a', 'b', 'new', 'mpilgrim'] >>> a_list.pop() ① 'mpilgrim' >>> a_list ['a', 'b', 'new'] >>> a_list.pop(1) ② 'b' >>> a_list ['a', 'new'] >>> a_list.pop() 'new' >>> a_list.pop() 'a' >>> a_list.pop() ③ Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: pop from empty list
pop() 列表方法將刪除列表中最后的元素,并返回所刪除的值。pop() 方法一個位置索引值。它將刪除該元素,將其后所有元素移位以“填補縫隙”,然后返回它刪除的值。pop() 將會引發一個例外。?不帶參數調用的
pop()列表方法就像 Perl 中的pop()函數。它從列表中刪除最后一個元素并返回所刪除元素的值。Perl 還有另一個函數shift(),可用于刪除第一個元素并返回其值;在 Python 中,該函數相當于a_list.pop(0)。
可以在 if 這樣的 布爾類型上下文環境中 使用列表。
>>> def is_it_true(anything):
... if anything:
... print("yes, it's true")
... else:
... print("no, it's false")
...
>>> is_it_true([]) ①
no, it's false
>>> is_it_true(['a']) ②
yes, it's true
>>> is_it_true([False]) ③
yes, it's true
?
元素 是不可變的列表。一旦創建之后,用任何方法都不可以修改元素。
>>> a_tuple = ("a", "b", "mpilgrim", "z", "example") ①
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple[0] ②
'a'
>>> a_tuple[-1] ③
'example'
>>> a_tuple[1:3] ④
('b', 'mpilgrim')
a_tuple[0] 。元組和列表的主要區別是元組不能進行修改。用技術術語來說,元組是 不可變更 的。從實踐的角度來說,沒有可用于修改元組的方法。列表有像 append()、 extend()、 insert()、remove() 和 pop() 這樣的方法。這些方法,元組都沒有。可以對元組進行切片操作(因為該方法創建一個新的元組),可以檢查元組是否包含了特定的值(因為該操作不修改元組),還可以……就那么多了。
# continued from the previous example
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple.append("new") ①
Traceback (innermost last):
File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'append'
>>> a_tuple.remove("z") ②
Traceback (innermost last):
File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'remove'
>>> a_tuple.index("example") ③
4
>>> "z" in a_tuple ④
True
append() 或 extend() 方法。remove() 或 pop() 方法。in 運算符檢查某元素是否存在于元組中。那么元組有什么好處呢?
assert 語句顯示該數據是常量,特別的想法(及特別的功能)必須重寫。(??)?元組可轉換成列表,反之亦然。內建的
tuple()函數接受一個列表參數,并返回一個包含同樣元素的元組,而list()函數接受一個元組參數并返回一個列表。從效果上看,tuple()凍結列表,而list()融化元組。
可以在 if 這樣的 布爾類型上下文環境中 使用元組。
>>> def is_it_true(anything):
... if anything:
... print("yes, it's true")
... else:
... print("no, it's false")
...
>>> is_it_true(()) ①
no, it's false
>>> is_it_true(('a', 'b')) ②
yes, it's true
>>> is_it_true((False,)) ③
yes, it's true
>>> type((False)) ④
<class 'bool'>
>>> type((False,))
<class 'tuple'>
以下是一種很酷的編程捷徑:在 Python 中,可使用元組來一次賦多值。
>>> v = ('a', 2, True)
>>> (x, y, z) = v ①
>>> x
'a'
>>> y
2
>>> z
True
(x, y, z) 是包含三個變量的元組。將其中一個賦值給另一個將會把 v 中的每個值按順序賦值給每一個變量。該特性有多種用途。假設需要將某個名稱指定某個特定范圍的值。可以使用內建的 range() 函數進行多變量賦值以快速地進行連續變量賦值。
>>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7) ① >>> MONDAY ② 0 >>> TUESDAY 1 >>> SUNDAY 6
range() 函數構造了一個整數序列。(從技術上來說, range() 函數返回的既不是列表也不是元組,而是一個 迭代器,但稍后您將學到它們的區別。) MONDAY、 TUESDAY、 WEDNESDAY、 THURSDAY、 FRIDAY、 SATURDAY 和 SUNDAY 是您所定義的變量。(本例來自于 calendar 模塊,該短小而有趣的模塊打印日歷,有點像 UNIX 程序 cal 。該 calendar 模塊為星期數定義了整數常量。1,如此類推。還可以使用多變量賦值創建返回多值的函數,只需返回一個包含所有值的元組。調用者可將返回值視為一個簡單的元組,或將其賦值給不同的變量。許多標準 Python 類庫這么干,包括在下一章將學到的 os 模塊。
?
集合set 是裝有獨特值的無序“袋子”。一個簡單的集合可以包含任何數據類型的值。如果有兩個集合,則可以執行像聯合、交集以及集合求差等標準集合運算。
重中之重。創建集合非常簡單。
>>> a_set = {1} ①
>>> a_set
{1}
>>> type(a_set) ②
<class 'set'>
>>> a_set = {1, 2} ③
>>> a_set
{1, 2}
{})。還可以 列表 為基礎創建集合。
>>> a_list = ['a', 'b', 'mpilgrim', True, False, 42] >>> a_set = set(a_list) ① >>> a_set ② {'a', False, 'b', True, 'mpilgrim', 42} >>> a_list ③ ['a', 'b', 'mpilgrim', True, False, 42]
set() 函數。(懂得如何實現集合的學究可能指出這實際上并不是調用某個函數,而是對某個類進行實例化。我保證在本書稍后的地方將會學到其中的區別。目前而言,僅需知道 set() 行為與函數類似,以及它返回一個集合。)還沒有任何值?沒有問題。可以創建一個空的集合。
>>> a_set = set() ① >>> a_set ② set() >>> type(a_set) ③ <class 'set'> >>> len(a_set) ④ 0 >>> not_sure = {} ⑤ >>> type(not_sure) <class 'dict'>
set() 。{} 吧 ?該符號表示一個空的字典,而不是一個空的集合。本章稍后您將學到關于字典的內容。有兩種方法可向現有集合中添加值: add() 方法和 update() 方法。
>>> a_set = {1, 2}
>>> a_set.add(4) ①
>>> a_set
{1, 2, 4}
>>> len(a_set) ②
3
>>> a_set.add(1) ③
>>> a_set
{1, 2, 4}
>>> len(a_set) ④
3
add() 方法接受單個可以是任何數據類型的參數,并將該值添加到集合之中。
>>> a_set = {1, 2, 3}
>>> a_set
{1, 2, 3}
>>> a_set.update({2, 4, 6}) ①
>>> a_set ②
{1, 2, 3, 4, 6}
>>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13}) ③
>>> a_set
{1, 2, 3, 4, 5, 6, 8, 9, 13}
>>> a_set.update([10, 20, 30]) ④
>>> a_set
{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
update() 方法僅接受一個集合作為參數,并將其所有成員添加到初始列表中。其行為方式就像是對參數集合中的每個成員調用 add() 方法。update() 方法。如果調用時傳遞了兩個集合, update() 將會被每個集合中的每個成員添加到初始的集合當中(丟棄重復值)。update() 方法還可接受一些其它數據類型的對象作為參數,包括列表。如果調用時傳入列表,update() 將會把列表中所有的元素添加到初始集合中。有三種方法可以用來從集合中刪除某個值。前兩種,discard() 和 remove() 有細微的差異。
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set
{1, 3, 36, 6, 10, 45, 15, 21, 28}
>>> a_set.discard(10) ①
>>> a_set
{1, 3, 36, 6, 45, 15, 21, 28}
>>> a_set.discard(10) ②
>>> a_set
{1, 3, 36, 6, 45, 15, 21, 28}
>>> a_set.remove(21) ③
>>> a_set
{1, 3, 36, 6, 45, 15, 28}
>>> a_set.remove(21) ④
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 21
discard() 接受一個單值作為參數,并從集合中刪除該值。discard() 方法,它不進行任何操作。不產生錯誤;只是一條空指令。remove() 方法也接受一個單值作為參數,也從集合中將其刪除。remove() 方法引發一個 KeyError 例外。就像列表,集合也有個 pop() 方法。
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set.pop() ①
1
>>> a_set.pop()
3
>>> a_set.pop()
36
>>> a_set
{6, 10, 45, 15, 21, 28}
>>> a_set.clear() ②
>>> a_set
set()
>>> a_set.pop() ③
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'
pop() 方法從集合中刪除某個值,并返回該值。然而,由于集合是無序的,并沒有“最后一個”值的概念,因此無法控制刪除的是哪一個值。它基本上是隨機的。clear() 方法刪除集合中 所有 的值,留下一個空集合。它等價于 a_set = set(),該語句創建一個新的空集合,并用之覆蓋 a_set 變量的之前的值。KeyError 例外。Python 的 集合 類型支持幾種常見的運算。
>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
>>> 30 in a_set ①
True
>>> 31 in a_set
False
>>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
>>> a_set.union(b_set) ②
{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}
>>> a_set.intersection(b_set) ③
{9, 2, 12, 5, 21}
>>> a_set.difference(b_set) ④
{195, 4, 76, 51, 30, 127}
>>> a_set.symmetric_difference(b_set) ⑤
{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
in 運算符。其工作原理和列表的一樣。union() 方法返回一個新集合,其中裝著 在兩個 集合中出現的元素。intersection() 方法返回一個新集合,其中裝著 同時 在兩個集合中出現的所有元素。difference() 方法返回的新集合中,裝著所有在 a_set 出現但未在 b_set 中的元素。symmetric_difference() 方法返回一個新集合,其中裝著所有 只在其中一個 集合中出現的元素。這三種方法是對稱的。
# continued from the previous example >>> b_set.symmetric_difference(a_set) ① {3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127} >>> b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set) ② True >>> b_set.union(a_set) == a_set.union(b_set) ③ True >>> b_set.intersection(a_set) == a_set.intersection(b_set) ④ True >>> b_set.difference(a_set) == a_set.difference(b_set) ⑤ False
最后,有幾個您可能會問到的問題。
>>> a_set = {1, 2, 3}
>>> b_set = {1, 2, 3, 4}
>>> a_set.issubset(b_set) ①
True
>>> b_set.issuperset(a_set) ②
True
>>> a_set.add(5) ③
>>> a_set.issubset(b_set)
False
>>> b_set.issuperset(a_set)
False
False 。可在 if 這樣的 布爾類型上下文環境中 使用集合。
>>> def is_it_true(anything):
... if anything:
... print("yes, it's true")
... else:
... print("no, it's false")
...
>>> is_it_true(set()) ①
no, it's false
>>> is_it_true({'a'}) ②
yes, it's true
>>> is_it_true({False}) ③
yes, it's true
?
字典 是鍵值對的無序集合。向字典添加一個鍵的同時,必須為該鍵增添一個值。(之后可隨時修改該值。) Python 的字典為通過鍵獲取值進行了優化,而不是反過來。
?Python 中的字典與 Perl 5 中的 hash [散列]類似。在 Perl 5 中,散列存儲的變量總是以一個
%符開頭。在 Python 中,變量可以隨意命名,而 Python 內部跟蹤其數據類型。
創建字典非常簡單。其語法與 集合 的類似,但應當指定鍵值對而不是值。有了字典后,可以通過鍵來查找值。
>>> a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'} ①
>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> a_dict['server'] ②
'db.diveintopython3.org'
>>> a_dict['database'] ③
'mysql'
>>> a_dict['db.diveintopython3.org'] ④
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'db.diveintopython3.org'
'server' 為鍵,通過 a_dict['server'] 引用的關聯值為 'db.diveintopython3.org' 。'database' 為鍵,通過 a_dict['database'] 引用的關聯值為 'mysql' 。a_dict['server'] 為 'db.diveintopython3.org',而 a_dict['db.diveintopython3.org'] 會引發例外,因為 'db.diveintopython3.org' 并不是鍵。字典沒有預定義的大小限制。可以隨時向字典中添加新的鍵值對,或者修改現有鍵所關聯的值。繼續前面的例子:
>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> a_dict['database'] = 'blog' ①
>>> a_dict
{'server': 'db.diveintopython3.org', 'database': 'blog'}
>>> a_dict['user'] = 'mark' ②
>>> a_dict ③
{'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'}
>>> a_dict['user'] = 'dora' ④
>>> a_dict
{'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
>>> a_dict['User'] = 'mark' ⑤
>>> a_dict
{'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
'user',值為 'mark')出現在中間。事實上,在第一個例子中字典項按順序出現是個巧合;現在它們不按順序出現同樣也是個巧合。user 鍵的值改回 "mark" 嗎?不會!仔細看看該鍵——有個大寫的 U 出現在 "User" 中。字典鍵是區分大小寫的,因此該語句創建了一組新的鍵值對,而不是覆蓋既有的字典項。對你來說它們可能是一樣的,但對于 Python 而言它們是完全不同的。字典并非只能用于字符串。字典的值可以是任何數據類型,包括整數、布爾值、任何對象,甚至是其它的字典。而且就算在同一字典中,所有的值也無須是同一類型,您可根據需要混合匹配。字典的鍵要嚴格得多,可以是字符串、整數和其它一些類型。在同一字典中也可混合、匹配使用不同數據類型的鍵。
實際上,您已經在 your first Python program 見過一個將非字符串用作鍵的字典了。
SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
讓我們在交互式 shell 中剖析一下:
>>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
... 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
>>> len(SUFFIXES) ①
2
>>> 1000 in SUFFIXES ②
True
>>> SUFFIXES[1000] ③
['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
>>> SUFFIXES[1024] ④
['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
>>> SUFFIXES[1000][3] ⑤
'TB'
len() 函數將返回字典中鍵的數量。in 運算符以測試某個特定的鍵是否在字典中。1000 是 字典 SUFFIXES 的一個鍵;其值為一個 8 元素列表(確切地說,是 8 個字符串)。1024 是字典 SUFFIXES 的鍵;其值也是一個 8 元素列表。SUFFIXES[1000] 是列表,可以通過它們的 0 基點索引來獲取列表中的單個元素。可以在 if 這樣的 布爾類型上下文環境中 使用字典。
>>> def is_it_true(anything):
... if anything:
... print("yes, it's true")
... else:
... print("no, it's false")
...
>>> is_it_true({}) ①
no, it's false
>>> is_it_true({'a': 1}) ②
yes, it's true
?
NoneNone 是 Python 的一個特殊常量。它是一個 空 值。None 與 False 不同。None 不是 0 。None 不是空字符串。將 None 與任何非 None 的東西進行比較將總是返回 False 。
None 是唯一的空值。它有著自己的數據類型(NoneType)。可將 None 賦值給任何變量,但不能創建其它 NoneType 對象。所有值為 None 變量是相等的。
>>> type(None) <class 'NoneType'> >>> None == False False >>> None == 0 False >>> None == '' False >>> None == None True >>> x = None >>> x == None True >>> y = None >>> x == y True
None在 布爾類型上下文環境中, None 為假值,而 not None 為真值。
>>> def is_it_true(anything):
... if anything:
... print("yes, it's true")
... else:
... print("no, it's false")
...
>>> is_it_true(None)
no, it's false
>>> is_it_true(not None)
yes, it's true
?
? 2001–9 Mark Pilgrim