簡介

August 8, 2015 · View on GitHub

我們已經學習了許多使用周蟒與 Python 語言時常用的知識, 在這一章中,我們將要再學習一些額外的內容,使我們能更加完整地瞭解周蟒與 Python 語言。

特殊類別方法

周蟒與 Python 語言的類別(Class)其中的一些特殊類別方法(method)具有特殊的意義。 例如 "初始化"(init)、"刪除"(del) 和 "字串"(str) 類別方法,它們的重要性我們已經學習過了。

一般說來,特殊的類別方法都被用來模仿某個行為。例如,如果你想讓你的類別實體能使用 xkey 這樣的索引操作(就像使用列表和元組一樣), 那麼你只需要實現getitem 這個類別方法就可以了。 當 Python 直譯器在解譯你的類別實體時遇到 xkey 這樣的操作時,Python 直譯器會呼叫 getitem 這個類別方法。 如果你想知道的話,Python 直譯器也是這麼處理 list 類別的!

下面這個表格中列出了一些有用的特殊方法。如果你想要知道所有的特殊類別方法,你可以在《Python參考手冊》中找到所有的特殊類別方法列表。

http://docs.python.org/ref/specialnames.html

名稱英文名稱解釋
初始化(我, ...)init(self, ...)這個方法是用來初始化物件的。在一個新建的物件剛返回可使用時會呼叫這個類別方法。
刪除(我)del(self)這物件要被刪除前會呼叫這個類別方法。
字串(我)str(self)在我們需要將物件用字串顯示時 ("印出"(print) 或 "字串()"(str())) 會呼叫這個類別方法。
lt(我, 其他)lt(self, other)在使用 '小於'(<) 運算符比較這個物件跟另外一個物件時會呼叫這個類別方法。同樣地,所有的關聯運算符(+, >等等)都有相應的特殊類別方法。
getitem(我, 鍵)getitem(self, key)在使用 "x[鍵]"(xkey) 這樣形式的索引操作時會呼叫這個類別方法。
長度(我)len(self)在對序列物件使用內建的 len() 函式時會呼叫這個類別方法。

單行語句區塊

現在你應該已相當瞭解在周蟒與 Python 語言中,每一個語句區塊都是以縮排的層次來與其它區塊區分開來的。 這在多數情況下是正確的,但是如果你的語句塊只包含一句語句,那麼你可以直接在條件語句(或循環語句)的同一行指明它。 下面這個例子清晰地說明了這一點:

$ zhpy
>>> 標誌 = 真
>>> 如果 標誌 == 真: 印出 '好'
...

>>>

python 版:

$ python
>>> flag = True
>>> if flag == True: print 'Yes'
...
Yes
>>>

如你所見,單行語句區塊被寫在同一行中,而不是獨立寫在另外一行中。 雖然這樣做可以使你的程式變得小一些,不過我強烈建議你不要使用這種方式。在此一提的原因只是讓本書更完整罷了.

另外還請注意, 在使用互動式的周蟒與 Python 直譯器時,它會通過恰當地改變提示符來幫助你輸入語句。 在上面的例子中,在你輸入了 if 語句之後,周蟒與 Python 直譯器把提示符改變為...以表示語句還沒有結束。 我們再按一次確認(Enter)鍵後,周蟒或 Python 直譯器才會開始解譯,編譯,並且立即執行這段語句。 然後返回原來的提示符並且等待下一行的輸入。

列表生成 (List Comprehension)

列表生成,可以從一個已有的序列衍生出一個新的列表。 例如,你有一個數值的列表,而你想要得到一個數值大於2的對應的列表,並使其中所有的數都是原來的2倍。 你可以建立一個空的列表, 並一個個將結果算出後填入列表中,或者你也可以使用列表生成的方式來產生這個對應的列表:

$ zhpy
>>> 列表1 = [2, 3, 4]
>>> 列表2 = [2*值 取 值 自 列表1 如果 值 > 2]
>>> 列表3
[6, 8]
>>>

python 版:

$ python
>>> list_one = [2, 3, 4]
>>> list_two = [2*i for i in list_one if i > 2]
>>> list_two
[6, 8]
>>>

程式如何運作

我們透過對原本列表1(list_one)中的每個滿足條件("如果 值 > 2"(if i > 2))的數值("取 值 自 列表1"(for i in list_one)) 作數學運算("2*值"(2*i)), 來產生一個新的列表。 這種格式的語句裡可以不用包含條件式。(不加條件式就沒有"如果 值 > 2"(if i > 2)這樣讓列表中所有值都大於2的效果)。

注意我們只是產生了一個新的列表, 並沒有修改到原來的列表。

使用元組和列表接受函式參數 (Receiving tuples and lists in functions)

周蟒與 Python 語言裡有種特殊的用法: 周蟒與 Pyhton 函式能分別使用具有 **和****前綴的函式參數來將取得函式參數的元組或列表:

$ zhpy
>>> 定義 加總(乘方, *參數):
...     總和 = 0
...     取 值 自 參數:
...     總和 += i
...     返回 總和
...
>>> 加總(2, 3, 4)
7
>>> 加總(2, 10)
10
>>>
```**

python 版:

$ python

def sum(power, *args): ... total = 0 ... for i in args: ... total += i ... return total ... sum(2, 3, 4) 7 sum(2, 10) 10


例子裡因為我們用到了一個以星號(**)為前綴的"參數"(args) 函式參數,所有傳給函式的額外參數都會以元組的形式儲存到"參數"(args) 變量中。
如果我們改使用兩個星號(****)為前綴的"參數"(args) 函式參數, 則所有傳給函式的額外參數都會以鍵-值對的方式儲存在字典中。**

## 方程式(Lambda) 形式 ##

"方程式"(lambda) 語句被用來在運行中建立新函式物件。"方程式"(lambda) 語句基本上做的工作就是建立一個不具有名稱空間的函式:

$ zhpy

定義 建立重複器(n): ... 返回 方程式 s: s * n ... 兩次 = 建立重複器(2) 印出 兩次('word') wordword 印出 兩次(5) 10


python 版:

$ python

def make_repeater(n): ... return lambda s: s * n ... twice = make_repeater(2) print twice('word') wordword print twice(5) 10


### 程式如何運作 ###

我們傳回一個使用"建立重複器"(make\_repeater) 函式來建立的一個新函式物件。"方程式"(lambda) 語句在此被用來建立一個新函式物件。

"方程式"(lambda) 語句的冒號後面緊跟著一個單行表達式作為函式的本體,使用這個單行表達式等同於使用一般有具名的函式。 (即本例中可以另外寫一個函式來呼叫這個表達式, 可得到同樣輸出)

注意,方程式形式中只能使用表達式, "印出"(print) 語句也不能用在"方程式"(lambda) 形式中。

## 使用執行 (exec) 和評估 (eval) 語句 ##

"執行"(exec) 語句被用在執行儲存於字串格式中的 Python 程式。
例如,我們可以在運行時生成一個包含 Python 程式碼的字串,然後使用"執行"(exec) 語句來執行這些包含在字串中的語句:

$ zhpy

執行 'print "Hello World"' Hello World


python 版:

$ python

exec 'print "Hello World"' Hello World


eval 語句則是用來評估存儲在字串中的 Python 表達式:

$ zhpy

評估('2*3') 6


python 版:

$ python

eval('2*3') 6


周蟒的中文程式需使用"中文執行"(zh\_exec) 來取代"執行"(exec)以執行包含在字串中的語句:

$ zhpy

從 周蟒 導入 中文執行 中文執行('印出 "Hello World"') Hello World


python 版:

$ python

from zhpy import zh_exec zh_exec('印出 "Hello World"') Hello World


## 使用申明 (assert) 語句 ##

"申明"(assert) 語句用來'申明'某個條件是真的。
例如,如果你非常確信某個你使用的列表中至少包含有一個元素,而你只是想要確認這一點,並且在這個聲明不正確的時候引發一個錯誤,
那麼 "申明"(assert) 語句是在這種情形下的理想選擇。
當 "申明"(assert) 語句發現條件聲明是 "假"(false) 的時候,會"引發"(raise)一個"申明錯誤"(AssertionError):

$ zhpy

s = 'hello world' 申明 s 不為 空 申明 長度(s) > 0 申明 長度(s) == 0 # 這應該會引發錯誤 Traceback (most recent call last): File "", line 1, in ? AssertionError


python 版:

$ python

s = 'hello world' assert s is not None assert len(s) > 0 assert len(s) == 0 # this should fail Traceback (most recent call last): File "", line 1, in ? AssertionError


## 描述(repr) 函式 ##

"描述"(repr) 函式能用來取得物件的字串化資訊。反引號(也稱轉換符)可以完成相同的功能。注意,在大多數時候

評估(描述(物件)) == 物件


python 版:

eval(repr(object)) == object


這樣的表達式傳回的結果是有效(True)的:

$ zhpy

i = [] i.加入('item') i "['item']" 描述(i) "['item']" 評估(描述(i)) == i True


python 版:

$ python

i = [] i.append('item') i "['item']" repr(i) "['item']" eval(repr(i)) == i True


你可以通過定義 "描述"(repr) 類別方法來控制 "描述"(repr) 函式返回的內容。

# 結語 #

在這一章中,我們又學習了一些周蟒與 Python 語言的特色,然而我們仍未完全學習完周蟒與 Python 語言的所有特色。
不過,到目前為止,我們確實已經學習了絕大多數你在日常中會實際使用到的知識。
這些知識已經足以讓你能解決你在學習寫程式的過程中想解決的任何問題了。你可以在當你需要的時候去學習更深入的內容

接下來,我們會討論一下如何進一步深入探索周蟒與 Python。

[標準函式庫](StandardModules.md) | [後續學習](MoreInfo.md)