Learn Python (day 2)

1、Python 函數

當你需要一個函數的時候,就像這樣聲明它就行:

<pre name="code" class="python"><span style="font-family:Microsoft YaHei;color:#006600;">def approximate_size(size, a_kilobyte_is_1024_bytes=True):</span>

函數聲明以關鍵字 def 開頭,緊跟着函數的名稱,然後是用括號括起來的參數。多個參數以逗號分割。

同時注意,函數不定義一個返回數據類型。 Python 函數不指定它們的返回值的類型,甚至不指定它們是否返回一個值。(事實上,每個 Python 函數都返回一個值,如果這個函數曾經執行了 return 語句,它將返回那個值,否則它將返回 Python 裏面的空值 None。)


Python 函數是真正的好用。

(1)、Python 允許函數函數有默認值。如果函數被調用的時候沒有指定參數,那麼參數將使用默認值。不僅如此,通過使用命名參數還可以按照任何順序指定參數。


讓我們再看一下 approximate_size() 函數的聲明:

<span style="font-family:Microsoft YaHei;color:#006600;">def approximate_size(size, a_kilobyte_is_1024_bytes=True):</span>


第二個參數 a_kilobyte_is_1024_bytes 指定了一個默認值 True。 意思是這個參數是 optional (可選的),你可以在調用的時候不指定它,Python 將看成你調用的時候使用了 True 作爲第二個參數。


(2)、 Python允許指定變量名傳值

<span style="font-family:Microsoft YaHei;color:#006600;">>>> from humansize import approximate_size
>>> approximate_size(4000, a_kilobyte_is_1024_bytes=False)       ①
'4.0 KB'
>>> approximate_size(size=4000, a_kilobyte_is_1024_bytes=False)  ②
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, size=4000)  ③
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, 4000)       ④
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> approximate_size(size=4000, False)                           ⑤
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg</span>

這個對 approximate_size() 函數的調用給第一個參數((size)指定了值 4000,並且給名爲 a_kilobyte_is_1024_bytes 的參數指定了值 False。(那碰巧是第二個參數,但這沒有關係,馬上你就會瞭解到。)

這個對 approximate_size() 函數的調用給名爲 size 參數指定了值 4000,併爲名爲 a_kilobyte_is_1024_bytes 的參數指定了值 False。(這些命名參數碰巧和函數聲明時列出的參數順序一樣,但同樣不要緊。)

這個對 approximate_size() 函數的調用給名爲 a_kilobyte_is_1024_bytes 的參數指定了值 False,然後給名爲 size 的參數指定了值 4000。(看到了沒?我告訴過你順序沒有關係。)

這個調用會失敗,因爲你在命名參數後面緊跟了一個非命名(位置的)的參數,這個一定不會工作。從左到右的讀取參數列表,一旦你有一個命名的參數,剩下的參數也必須是命名的。

這個調用也會失敗,和前面一個調用同樣的原因。 是不是很驚訝?別忘了,你給名爲 size 的參數傳入了值 4000,那麼“顯然的” False 這個值意味着對應了 a_kilobyte_is_1024_bytes 參數。但是 Python 不按照這種方式工作。只要你有一個命名參數,它右邊的所有參數也都需要是命名參數。


注:Python函數往往返回 元組


2、 Python的註釋 
文檔字符串#
你可以通過使用一個文檔字符串(簡稱 docstring )的方式給 Python 添加文檔註釋。在這個程序中,這個 approximate_size() 函數有一個 docstring:

<span style="font-family:Microsoft YaHei;color:#006600;">def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    '''Convert a file size to human-readable form.

    Keyword arguments:
    size -- file size in bytes
    a_kilobyte_is_1024_bytes -- if True (default), use multiples of 1024
                                if False, use multiples of 1000

    Returns: string

    '''</span>


三重引號表示一個多行的字符串。在開始引號和結束引號之間的所有東西都屬於一個單獨的字符串的一部分,包括回車、前導空格、和其他引號字符。你可以在任何地方使用它們,但是你會發現大部分時候它們在定義 docstring (文檔註釋)的時候使用。☞三重引號也是一種容易的方法,用來定義一個同時包含單引號和雙引號的字符串,就像 Perl 5 裏面的 qq/.../ 一樣。三重引號之間的所有東西都是這個函數的 docstring (文檔字符串),用來用文檔描述這個函數是做什麼的。一個 docstring (文檔字符串),如果有的話,必須是一個函數裏面定義的第一個東西(也就是說,緊跟着函數聲明的下一行)。 你不需要嚴格的給你的每個函數提供一個 docstring (文檔字符串),但大部分時候你總是應該提供。我知道你在曾經使用過的每一種程序語言裏面聽說過這個,但是 Python 給你提供了額外的誘因:這個 docstring (文檔字符串)就像這個函數的一個屬性一樣在運行時有效。☞很多 Python 的集成開發環境(ide)使用 docstring (文檔字符串)來提供上下文敏感的文檔,以便於當你輸入一個函數名稱的時候,它的 docstring 會以一個提示文本的方式顯式出來。這可能會極其有用,但它只有在你寫出好的 docstring (文檔字符串)的時候纔有用。

3、 Python變量不需要聲明。需要使用的時候,聲明和賦值是一起的。

4、 Python內置數據結構。

Python 有多種內置數據類型。以下是比較重要的一些:

Booleans[布爾型] 或爲 True[真] 或爲 False[假]。

Numbers[數值型] 可以是 Integers[整數](1 和 2)、Floats[浮點數](1.1 和 1.2)、Fractions[分數](1/2 和 2/3);甚至是 Complex Number[複數]。

Strings[字符串型] 是 Unicode 字符序列,例如: 一份 html 文檔。

Bytes[字節] 和 Byte Arrays[字節數組], 例如: 一份 jpeg 圖像文件。

Lists[列表] 是值的有序序列。

Tuples[元組] 是有序而不可變的值序列。

Sets[集合] 是裝滿無序值的包裹。

Dictionaries[字典] 是鍵值對的無序包裹。

當然,還有更多的類型。在 Python 中一切均爲對象,因此存在像 module[模塊]、 function[函數]、 class[類]、 method[方法]、 file[文件] 甚至 compiled code[已編譯代碼] 這樣的類型。您已經見過這樣一些例子:模塊的 name、 函數的 docstrings 等等。將學到的包括 《類 與 迭代器》 中的 Classes[類],以及 《文件》 中的 Files[文件]。

Strings[字符串]和 Bytes[字節串]比較重要,也相對複雜,足以開闢獨立章節予以講述。讓我們先看看其它類型。

① Booleans : True  Fales (注意首字母大寫!)

唯一要注意的是

{

由於 Python 2 的一些遺留問題,布爾值可以當做數值對待。True 爲 1;False 爲 0 。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>

}(Python3中不能用了)


②數值類型

數值類型是可畏的。有太多類型可選了。

Python 同時支持 Integer[整型] 和 Floating Point[浮點型] 數值。無任何類型聲明可用於區分;Python 通過是否有 小數 點來分辨它們。

<pre name="code" class="python"><span style="font-family:Microsoft YaHei;color:#006600;">>>> type(1)                 ①
<class 'int'>
>>> isinstance(1, int)      ②
True
>>> 1 + 1                   ③
2
>>> 1 + 1.0                 ④
2.0
>>> type(2.0)
<class 'float'></span>

可以使用 type() 函數來檢測任何值或變量的類型。正如所料,1 爲 int 類型。
同樣,還可使用 isinstance() 函數判斷某個值或變量是否爲給定某個類型。
將一個 int 與一個 int 相加將得到一個 int 。
將一個 int 與一個 float 相加將得到一個 float 。Python 把 int 強制轉換爲 float 以進行加法運算;然後返回一個 float 類型的結果。


將整數強制轉換爲浮點數及反向轉換#


正如剛纔所看到的,一些運算符(如:加法)會根據需把整數強制轉換爲浮點數。也可自行對其進行強制轉換。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> float(2)                ①
2.0
>>> int(2.0)                ②
2
>>> int(2.5)                ③
2
>>> int(-2.5)               ④
-2
>>> 1.12345678901234567890  ⑤
1.1234567890123457
>>> type(1000000000000000)  ⑥
<class 'int'></span>
通過調用float() 函數,可以顯示地將 int 強制轉換爲 float。
毫不出奇,也可以通過調用 int() 將 float 強制轉換爲 int 。
int() 將進行取整,而不是四捨五入。
對於負數,int() 函數朝着 0 的方法進行取整。它是個真正的取整(截斷)函數,而不是 floor[地板]函數。
浮點數精確到小數點後 15 位。
整數可以任意大。
☞Python 2 對於int[整型] 和 long[長整型] 採用不同的數據類型。int 數據類型受到 sys.maxint 的限制,因平臺該限制也會有所不同,但通常是 232-1 。Python 3 只有一種整數類型,其行爲方式很有點像 Python 2 的舊 long[長整數] 類型。

常見數值運算#

對數值可進行各種類型的運算。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 11 / 2      ①
5.5
>>> 11 // 2     ②
5
>>> −11 // 2    ③
−6
>>> 11.0 // 2   ④
5.0
>>> 11 ** 2     ⑤
121
>>> 11 % 2      ⑥
1</span>
/ 運算符執行浮點除法。即便分子和分母都是 int,它也返回一個 float 浮點數。
// 運算符執行古怪的整數除法。如果結果爲正數,可將其視爲朝向小數位取整(不是四捨五入),但是要小心這一點。
當整數除以負數, // 運算符將結果朝着最近的整數“向上”四捨五入。從數學角度來說,由於 −6 比 −5 要小,它是“向下”四捨五入,如果期望將結果取整爲 −5,它將會誤導你。
// 運算符並非總是返回整數結果。如果分子或者分母是 float,它仍將朝着最近的整數進行四捨五入,但實際返回的值將會是 float 類型。
** 運算符的意思是“計算冪”,112 結果爲 121 。
% 運算符給出了進行整除之後的餘數。11 除以 2 結果爲 5 以及餘數 1,因此此處的結果爲 1。
☞在 Python 2 中,運算符 / 通常表示整數除法,但是可以通過在代碼中加入特殊指令,使其看起來像浮點除法。在 Python 3 中,/ 運算符總是表示浮點除法。

分數#

Python 並不僅僅侷限於整數和浮點數類型。它可以完成你在高中階段學過、但幾乎已經全部忘光的所有古怪數學運算。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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)</span>

爲啓用 fractions 模塊,必先引入 fractions 模塊。

爲定義一個分數,創建一個 Fraction 對象並傳入分子和分母。
可對分數進行所有的常規數學計算。運算返回一個新的 Fraction 對象。2 * (1/3) = (2/3)
Fraction 對象將會自動進行約分。(6/4) = (3/2)
在杜絕創建以零爲分母的分數方面,Python 有着良好的敏感性。

還可在 Python 中進行基本的三角函數運算。
<span style="font-family:Microsoft YaHei;color:#006600;">>>> import math
>>> math.pi                ①
3.1415926535897931
>>> math.sin(math.pi / 2)  ②
1.0
>>> math.tan(math.pi / 4)  ③
0.99999999999999989</span>
math 模塊中有一個代表 π 的常量,表示圓的周長與直徑之比率(圓周率)。
math 模塊包括了所有的基本三角函數,包括:sin()、 cos()、tan() 及像 asin() 這樣的變體函數。
然而要注意的是 Python 並不支持無限精度。tan(π / 4) 將返回 1.0,而不是 0.99999999999999989。
布爾上下文環境中的數值#

可以在 if 這樣的 布爾類型上下文環境中 使用數值。零值是 false[假],非零值是 true[真]。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>

您知道可以在 Python 交互式 Shell 中定義自己的函數嗎?只需在每行的結尾按 回車鍵 ,然後在某一空行按 回車鍵 結束。
在布爾類型上下文環境中,非零整數爲真;零爲假。
非零浮點數爲真; 0.0 爲假。請千萬小心這一點!如果有輕微的四捨五入偏差(正如在前面小節中看到的那樣,這並非不可能的事情),那麼 Python 將測試 0.0000000000001 而不是 0 ,並將返回一個 True 值。
分數也可在布爾類型上下文環境中使用。無論 n 爲何值,Fraction(0, n) 爲假。所有其它分數爲真。


③列表(list) →[1,2,3]

列表創建非常輕鬆:使用中括號包裹一系列以逗號分割的值即可。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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'</span>

首先,創建一個包含 5 個元素的列表。要注意的是它們保持了最初的順序。這並不是偶然的。列表是元素的有序集合。
列表可當做以零爲基點的數組使用。非空列表的首個元素始終是 a_list[0] 。
該 5 元素列表的最後一個元素是 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]。


定義列表後,可從其中獲取任何部分作爲新列表。該技術稱爲對列表進行 切片 。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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']</span>
通過指定兩個索引值,可以從列表中獲取稱作“切片”的某個部分。返回值是一個新列表,它包含列表(??切片)中所有元素,按順序從第一個切片索引開始(本例中爲 a_list[1]),截止但不包含第二個切片索引(本例中的 a_list[3])。
如果切片索引之一或兩者均爲負數,切片操作仍可進行。如果有幫助的話,您可以這麼思考:自左向右讀取列表,第一個切片索引指明瞭想要的第一個元素,第二個切片索引指明瞭第一個不想要的元素。返回值是兩者之間的任何值。 between.
列表是以零爲起點的,因此 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[:] 是對列表進行復制的一條捷徑。


有四種方法可用於向列表中增加元素。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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', 'Ω']</span>
+ 運算符連接列表以創建一個新列表。列表可包含任何數量的元素;沒有大小限制(除了可用內存的限制)。然而,如果內存是個問題,那就必須知道在進行連接操作時,將在內存中創建第二個列表。在該情況下,新列表將會立即被賦值給已有變量 a_list 。因此,實際上該行代碼包含兩個步驟 — 連接然後賦值 — 當處理大型列表時,該操作可能(暫時)消耗大量內存。
列表可包含任何數據類型的元素,單個列表中的元素無須全爲同一類型。下面的列表中包含一個字符串、一個浮點數和一個整數。
append() 方法向列表的尾部添加一個新的元素。(現在列表中有 四種 不同數據類型!)
列表是以類的形式實現的。“創建”列表實際上是將一個類實例化。因此,列表有多種方法可以操作。extend() 方法只接受一個列表作爲參數,並將該參數的每個元素都添加到原有的列表中。
insert() 方法將單個元素插入到列表中。第一個參數是列表中將被頂離原位的第一個元素的位置索引。列表中的元素並不一定要是唯一的;比如說:現有兩個各自獨立的元素,其值均爲 'Ω':,第一個元素 a_list[0] 以及最後一個元素 a_list[6] 。
☞a_list.insert(0, value) 就像是 Perl 中的 unshift() 函數。它將一個元素添加到列表的頭部,所有其它的元素都被頂理原先的位置以騰出空間。

讓我們進一步看看 append() 和 extend() 的區別。
<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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']</span>
extend() 方法只接受一個參數,而該參數總是一個列表,並將列表 a_list 中所有的元素都添加到該列表中。
如果開始有個 3 元素列表,然後將它與另一個 3 元素列表進行 extend 操作,結果是將獲得一個 6 元素列表。
另一方面, append() 方法只接受一個參數,但可以是任何數據類型。在此,對一個 3 元素列表調用 append() 方法。
如果開始的時候有個 6 元素列表,然後將一個列表 append[添加]上去,結果就會……得到一個 7 元素列表。爲什麼是 7 個?因爲最後一個元素(剛剛 append[添加] 的元素) 本身是個列表 。列表可包含任何類型的數據,包括其它列表。這可能是你所需要的結果,也許不是。但如果這就是你想要的,那這就是你所得到的。


在列表中檢索值

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
如你所期望, 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,可能會導致調整過程變得不那麼有趣!


從列表中刪除元素

列表可以自動拓展或者收縮。您已經看到了拓展部分。也有幾種方法可從列表中刪除元素。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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'</span>
可使用 del 語句從列表中刪除某個特定元素。
刪除索引 1 之後再訪問索引 1 將 不會 導致錯誤。被刪除元素之後的所有元素將移動它們的位置以“填補”被刪除元素所產生的“縫隙”。
不知道位置索引?這不成問題,您可以通過值而不是索引刪除元素。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
還可以通過 remove() 方法從列表中刪除某個元素。remove() 方法接受一個 value 參數,並刪除列表中該值的第一次出現。同樣,被刪除元素之後的所有元素將會將索引位置下移,以“填補縫隙”。列表永遠不會有“縫隙”。
您可以盡情地調用 remove() 方法,但如果試圖刪除列表中不存在的元素,它將引發一個例外。


另一有趣的列表方法是 pop() 。pop() 方法是從列表刪除元素的另一方法,但有點變化。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
如果不帶參數調用, pop() 列表方法將刪除列表中最後的元素,並返回所刪除的值。
可以從列表中 pop[彈出]任何元素。只需傳給 pop() 方法一個位置索引值。它將刪除該元素,將其後所有元素移位以“填補縫隙”,然後返回它刪除的值。
對空列表調用 pop() 將會引發一個例外。

☞不帶參數調用的 pop() 列表方法就像 Perl 中的 pop() 函數。它從列表中刪除最後一個元素並返回所刪除元素的值。Perl 還有另一個函數 shift(),可用於刪除第一個元素並返回其值;在 Python 中,該函數相當於 a_list.pop(0) 。


注:空列表爲假;其它所有列表爲真。


元組(tuple) → (1,2,3)

元組 是不可變的列表。一旦創建之後,用任何方法都不可以修改元組。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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')</span>

元組的定義方式和列表相同,除了整個元素的集合都用圓括號,而不是方括號閉合。

和列表一樣,元組的元素都有確定的順序。元組的索引也是以零爲基點的,和列表一樣,因此非空元組的第一個元素總是 a_tuple[0] 。

負的索引從元組的尾部開始計數,這和列表也是一樣的。

和列表一樣,元組也可以進行切片操作。對列表切片可以得到新的列表;對元組切片可以得到新的元組。

元組和列表的主要區別是元組不能進行修改。用技術術語來說,元組是 不可變更 的。從實踐的角度來說,沒有可用於修改元組的方法。列表有像 append()、 extend()、 insert()、remove() 和 pop() 這樣的方法。這些方法,元組都沒有。可以對元組進行切片操作(因爲該方法創建一個新的元組),可以檢查元組是否包含了特定的值(因爲該操作不修改元組),還可以……就那麼多了。


<span style="font-family:Microsoft YaHei;color:#006600;"># 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</span>

無法向元組添加元素。元組沒有 append() 或 extend() 方法。

不能從元組中刪除元素。元組沒有 remove() 或 pop() 方法。

可以 在元組中查找元素,由於該操作不改變元組。

還可以使用 in 運算符檢查某元素是否存在於元組中。


那麼元組有什麼好處呢?


元組的速度比列表更快。如果定義了一系列常量值,而所需做的僅是對它進行遍歷,那麼請使用元組替代列表。

對不需要改變的數據進行“寫保護”將使得代碼更加安全。使用元組替代列表就像是有一條隱含的 assert 語句顯示該數據是常量,特別的想法(及特別的功能)必須重寫。(??)

一些元組可用作字典鍵(特別是包含字符串、數值和其它元組這樣的不可變數據的元組)。列表永遠不能當做字典鍵使用,因爲列表不是不可變的。

☞元組可轉換成列表,反之亦然。內建的 tuple() 函數接受一個列表參數,並返回一個包含同樣元素的元組,而 list() 函數接受一個元組參數並返回一個列表。從效果上看, tuple() 凍結列表,而 list() 融化元組。


布爾上下文環境中的元組#


可以在 if 這樣的 布爾類型上下文環境中 使用元組。

<pre name="code" class="python"><span style="font-family:Microsoft YaHei;color:#006600;">>>> 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'></span>

在布爾類型上下文環境中,空元組爲假值。

任何至少包含一個上元素的元組爲真值。

任何至少包含一個上元素的元組爲真值。元素的值無關緊要。不過此處的逗號起什麼作用呢?

爲創建單元素元組,需要在值之後加上一個逗號。沒有逗號,Python 會假定這只是一對額外的圓括號,雖然沒有害處,但並不創建元組。


###同時賦多個值#

以下是一種很酷的編程捷徑:在 Python 中,可使用元組來一次賦多值。

<pre name="code" class="python"><span style="font-family:Microsoft YaHei;color:#006600;">>>> v = ('a', 2, True)
>>> (x, y, z) = v       ①
>>> x
'a'
>>> y
2
>>> z
True</span>

v 是一個三元素的元組,而 (x, y, z) 是包含三個變量的元組。將其中一個賦值給另一個將會把 v 中的每個值按順序賦值給每一個變量。

該特性有多種用途。假設需要將某個名稱指定某個特定範圍的值。可以使用內建的 range() 函數進行多變量賦值以快速地進行連續變量賦值。

<pre name="code" class="python"><span style="font-family:Microsoft YaHei;color:#006600;">>>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)  ①
>>> MONDAY                                                                       ②
0
>>> TUESDAY
1
>>> SUNDAY
6</span>

內建的 range() 函數構造了一個整數序列。(從技術上來說, range() 函數返回的既不是列表也不是元組,而是一個 迭代器,但稍後您將學到它們的區別。) MONDAY、 TUESDAY、 WEDNESDAY、 THURSDAY、 FRIDAY、 SATURDAY 和 SUNDAY 是您所定義的變量。(本例來自於 calendar 模塊,該短小而有趣的模塊打印日曆,有點像 unix 程序 cal 。該 calendar 模塊爲星期數定義了整數常量。

現在,每個變量都有其值了: MONDAY 爲 0, TUESDAY 爲 1,如此類推。

還可以使用多變量賦值創建返回多值的函數,只需返回一個包含所有值的元組。調用者可將返回值視爲一個簡單的元組,或將其賦值給不同的變量。許多標準 Python 類庫這麼幹,包括在下一章將學到的 os 模塊。


⑤集合(set)→{1,2,3}

集合set 是裝有獨特值的無序“袋子”。一個簡單的集合可以包含任何數據類型的值。如果有兩個集合,則可以執行像聯合、交集以及集合求差等標準集合運算。

創建集合

重中之重。創建集合非常簡單。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> a_set = {1}     ①
>>> a_set
{1}
>>> type(a_set)     ②
<class 'set'>
>>> a_set = {1, 2}  ③
>>> a_set
{1, 2}</span>
要創建只包含一個值的集合,僅需將該值放置於花括號之間。({})。
實際上,集合以 類 的形式實現,但目前還無須考慮這一點。
要創建多值集合,請將值用逗號分開,並用花括號將所有值包裹起來。
還可以 列表 爲基礎創建集合。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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]</span>
要從列表創建集合,可使用 set() 函數。(懂得如何實現集合的學究可能指出這實際上並不是調用某個函數,而是對某個類進行實例化。我保證在本書稍後的地方將會學到其中的區別。目前而言,僅需知道 set() 行爲與函數類似,以及它返回一個集合。)
正如我之前提到的,簡單的集合可以包括任何數據類型的值。而且,如我之前所提到的,集合是 無序的。該集合並不記得用於創建它的列表中元素的最初順序。如果向集合中添加元素,它也不會記得添加的順序。
初始的列表並不會發生變化。
還沒有任何值?沒有問題。可以創建一個空的集合。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> a_set = set()    ①
>>> a_set            ②
set()
>>> type(a_set)      ③
<class 'set'>
>>> len(a_set)       ④
0
>>> not_sure = {}    ⑤
>>> type(not_sure)
<class 'dict'></span>
要創建空集合,可不帶參數調用 set() 。
打印出來的空集合表現形式看起來有點兒怪。也許,您期望看到一個 {} 吧 ?該符號表示一個空的字典,而不是一個空的集合。本章稍後您將學到關於字典的內容。
儘管打印出的形式奇怪,這 確實是 一個集合……
…… 同時該集合沒有任何成員。
由於從 Python 2 沿襲而來歷史的古怪規定,不能使用兩個花括號來創建空集合。該操作實際創建一個空字典,而不是一個空集合。


修改集合

有兩種方法可向現有集合中添加值: add() 方法和 update() 方法。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
add() 方法接受單個可以是任何數據類型的參數,並將該值添加到集合之中。
該集合現在有三個成員了。
集合是裝 唯一值 的袋子。如果試圖添加一個集合中已有的值,將不會發生任何事情。將不會引發一個錯誤;只是一條空操作。
該集合 仍然 只有三個成員。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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}</span>
update() 方法僅接受一個集合作爲參數,並將其所有成員添加到初始列表中。其行爲方式就像是對參數集合中的每個成員調用 add() 方法。
由於集合不能包含重複的值,因此重複的值將會被忽略。
實際上,可以帶任何數量的參數調用 update() 方法。如果調用時傳遞了兩個集合, update() 將會被每個集合中的每個成員添加到初始的集合當中(丟棄重複值)。
update() 方法還可接受一些其它數據類型的對象作爲參數,包括列表。如果調用時傳入列表,update() 將會把列表中所有的元素添加到初始集合中。


從集合中刪除元素#
有三種方法可以用來從集合中刪除某個值。前兩種,discard() 和 remove() 有細微的差異。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
discard() 接受一個單值作爲參數,並從集合中刪除該值。
如果針對一個集合中不存在的值調用 discard() 方法,它不進行任何操作。不產生錯誤;只是一條空指令。
remove() 方法也接受一個單值作爲參數,也從集合中將其刪除。
區別在這裏:如果該值不在集合中,remove() 方法引發一個 KeyError 例外。


就像列表,集合也有個 pop() 方法

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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'</span>
pop() 方法從集合中刪除某個值,並返回該值。然而,由於集合是無序的,並沒有“最後一個”值的概念,因此無法控制刪除的是哪一個值。它基本上是隨機的。
clear() 方法刪除集合中 所有 的值,留下一個空集合。它等價於 a_set = set(),該語句創建一個新的空集合,並用之覆蓋 a_set 變量的之前的值。
試圖從空集合中彈出某值將會引發 KeyError 例外。


常見集合操作#
Python 的 集合 類型支持幾種常見的運算。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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}</span>
要檢測某值是否是集合的成員,可使用 in 運算符。其工作原理和列表的一樣。
union() 方法返回一個新集合,其中裝着 在兩個 集合中出現的元素。
intersection() 方法返回一個新集合,其中裝着 同時 在兩個集合中出現的所有元素。
difference() 方法返回的新集合中,裝着所有在 a_set 出現但未在 b_set 中的元素。
symmetric_difference() 方法返回一個新集合,其中裝着所有 只在其中一個 集合中出現的元素。
這三種方法是對稱的。

<span style="font-family:Microsoft YaHei;color:#006600;"># 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</span>
a_set 與 b_set 的對稱差分 看起來 和b_set 與 a_set 的對稱差分不同,但請記住:集合是無序的。任何兩個包含所有同樣值(無一遺漏)的集合可認爲是相等的。
而這正是這裏發生的事情。不要被 Python Shell 對這些集合的輸出形式所愚弄了。它們包含相同的值,因此是相等的。
對兩個集合的 Union[並集]操作也是對稱的。
對兩個集合的 Intersection[交集]操作也是對稱的。
對兩個集合的 Difference[求差]操作不是對稱的。這是有意義的;它類似於從一個數中減去另一個數。操作數的順序會導致結果不同。


最後,有幾個您可能會問到的問題。

<span style="font-family:Microsoft YaHei;color:#006600;">>>> 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</span>
a_set 是 b_set 的 子集 — 所有 a_set 的成員均爲 b_set 的成員。
同樣的問題反過來說, b_set 是 a_set 的 超集,因爲 a_set 的所有成員均爲 b_set 的成員。
一旦向 a_set 添加一個未在 b_set 中出現的值,兩項測試均返回 False 。

在布爾類型上下文環境中,空集合爲假值。
任何至少包含一個上元素的集合爲真值。
任何至少包含一個上元素的集合爲真值。元素的值無關緊要。


⑥字典(dict)→{a:1,b:2,c:{a:1,b:2},d:(1,2,3)}

字典並非只能用於字符串。字典的值可以是任何數據類型,包括整數、布爾值、任何對象,甚至是其它的字典。而且就算在同一字典中,所有的值也無須是同一類型,您可根據需要混合匹配。字典的鍵要嚴格得多,可以是字符串、整數和其它一些類型。在同一字典中也可混合、匹配使用不同數據類型的鍵。

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}


在布爾類型上下文環境中,空字典爲假值。
至少包含一個鍵值對的字典爲真值。



基本數據類型就這點了,確實初步可以看出比java c 這種強太多,但是功能多也得記住纔好用啊!


ps:Python大名鼎鼎的縮進編碼應該不用提示了吧


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章