1. 程式人生 > 其它 >條件、迴圈及其他語句

條件、迴圈及其他語句

條件、迴圈及其他語句

你現在肯定有點不耐煩了。這些資料型別確實好,可你卻沒法使用它們來做什麼,不是嗎?
下面加快點速度。你已見過幾種語句(print語句、import語句和賦值語句),先來看看這些
語句的其他一些用法,再深入探討條件語句和迴圈語句。然後,我們將介紹列表推導,它們雖然
是表示式,但工作原理幾乎與條件語句和迴圈語句相同。最後,我們將介紹pass、del和exec。

5.1 再談 print 和 import

隨著你對Python的認識越來越深入,可能發現有些你自以為很熟悉的方面隱藏著讓人驚喜的
特性。下面就來看看print和import隱藏的幾個特性。雖然print現在實際上是一個函式,但以前
卻是一種語句,因此在這裡進行討論。

對很多應用程式來說,使用模組logging來寫入日誌比使用print更合適,詳情請參閱第19章。

5.1.1 列印多個引數

你知道,print可用於列印一個表示式,這個表示式要麼是字串,要麼將自動轉換為字元
串。但實際上,你可同時列印多個表示式,條件是用逗號分隔它們:

>>> print('Age:', 42) 
Age: 42 

如你所見,在引數之間插入了一個空格字元。在你要合併文字和變數值,而又不想使用字元
串格式設定功能時,這種行為很有幫助。

>>> name = 'Gumby' 
>>> salutation = 'Mr.' 
>>> greeting = 'Hello,' 
>>> print(greeting, salutation, name) 
Hello, Mr. Gumby 

如果字串變數greeting不包含逗號,如何在結果中新增呢?你不能像下面這樣做:

print(greeting, ',', salutation, name) 

因為這將在逗號前新增一個空格。下面是一種可行的解決方案:

print(greeting + ',', salutation, name) 

它將逗號和變數greeting相加。如果需要,可自定義分隔符:

>>> print("I", "wish", "to", "register", "a", "complaint", sep="_") 
I_wish_to_register_a_complaint 

你還可自定義結束字串,以替換預設的換行符。例如,如果將結束字串指定為空字串,
以後就可繼續列印到當前行。'

print('Hello,', end='') 
print('world!')

上述程式碼列印Hello, world!①。

① 僅當這些程式碼包含在指令碼中時才如此。在互動式Python會話中,將分別執行每條語句並列印其內容。

5.1.2 匯入時重新命名

從模組匯入時,通常使用

import somemodule

或使用

from somemodule import somefunction 

from somemodule import somefunction, anotherfunction, yetanotherfunction 

from somemodule import * 

僅當你確定要匯入模組中的一切時,採用使用最後一種方式。但如果有兩個模組,它們都包
含函式open,該如何辦呢?你可使用第一種方式匯入這兩個模組,並像下面這樣呼叫函式:

module1.open(...) 
module2.open(...) 

但還有一種辦法:在語句末尾新增as子句並指定別名。下面是一個匯入整個模組並給它指定
別名的例子:

>>> import math as foobar 
>>> foobar.sqrt(4) 
2.0 

下面是一個匯入特定函式並給它指定別名的例子:

>>> from math import sqrt as foobar 
>>> foobar(4) 
2.0 

對於前面的函式open,可像下面這樣匯入它們:

from module1 import open as open1 
from module2 import open as open2 

有些模組(如os.path)組成了層次結構(一個模組位於另一個模組中)。有關模組結構
的詳細資訊,請參閱10.1.4節。

5.2 賦值魔法

即便是不起眼的賦值語句也蘊藏著一些使用竅門。

5.2.1 序列解包

賦值語句你見過很多,有的給變數賦值,還有的給資料結構的一部分(如列表中的元素和切
片,或者字典項)賦值,但還有其他型別的賦值語句。例如,可同時(並行)給多個變數賦值:

>>> x, y, z = 1, 2, 3 
>>> print(x, y, z) 
1 2 3 

看似用處不大?看好了,使用這種方式還可交換多個變數的值。

>>> x, y = y, x 
>>> print(x, y, z) 
2 1 3 

實際上,這裡執行的操作稱為序列解包(或可迭代物件解包):將一個序列(或任何可迭代
物件)解包,並將得到的值儲存到一系列變數中。下面用例子進行解釋。

>>> values = 1, 2, 3 
>>> values 
(1, 2, 3) 
>>> x, y, z = values 
>>> x 
1

這在使用返回元組(或其他序列或可迭代物件)的函式或方法時很有用。假設要從字典中隨
便獲取(或刪除)一個鍵值對,可使用方法popitem,它隨便獲取一個鍵值對並以元組的方式
返回。接下來,可直接將返回的元組解包到兩個變數中。

>>> scoundrel = {'name': 'Robin', 'girlfriend': 'Marion'} 
>>> key, value = scoundrel.popitem() 
>>> key 
'girlfriend' 
>>> value 
'Marion' 

這讓函式能夠返回被打包成元組的多個值,然後通過一條賦值語句輕鬆地訪問這些值。要解
包的序列包含的元素個數必須與你在等號左邊列出的目標個數相同,否則Python將引發異常。

>>> x, y, z = 1, 2 
Traceback (most recent call last): 
 File "<stdin>", line 1, in <module> 
ValueError: need more than 2 values to unpack 
>>> x, y, z = 1, 2, 3, 4 
Traceback (most recent call last): 
 File "<stdin>", line 1, in <module> 
ValueError: too many values to unpack 

可使用星號運算子(*)來收集多餘的值,這樣無需確保值和變數的個數相同,如下例所示:

>>> a, b, *rest = [1, 2, 3, 4] 
>>> rest 
[3, 4] 

還可將帶星號的變數放在其他位置。

>>> name = "Albus Percival Wulfric Brian Dumbledore" 
>>> first, *middle, last = name.split() 
>>> middle 
['Percival', 'Wulfric', 'Brian'] 

賦值語句的右邊可以是任何型別的序列,但帶星號的變數最終包含的總是一個列表。在變數
和值的個數相同時亦如此。

>>> a, *b, c = "abc" 
>>> a, b, c 
('a', ['b'], 'c') 

這種收集方式也可用於函式引數列表中(參見第6章)。

5.2.2 鏈式賦值

鏈式賦值是一種快捷方式,用於將多個變數關聯到同一個值。這有點像前一節介紹的並行賦
值,但只涉及一個值:

x = y = somefunction() 

上述程式碼與下面的程式碼等價:

y = somefunction() 
x = y 

請注意,這兩條語句可能與下面的語句不等價:

x = somefunction() 
y = somefunction() 

有關這方面的詳細資訊,請參閱5.4.6節介紹相同運算子(is)的部分。

5.2.3 增強賦值

可以不編寫程式碼x = x + 1,而將右邊表示式中的運算子(這裡是+)移到賦值運算子(=)
的前面,從而寫成x += 1。這稱為增強賦值,適用於所有標準運算子,如*、/、%等。

>>> x = 2 
>>> x += 1 
>>> x *= 2 
>>> x 
6 

增強賦值也可用於其他資料型別(只要使用的雙目運算子可用於這些資料型別)。

>>> fnord = 'foo' 
>>> fnord += 'bar' 
>>> fnord *= 2 
>>> fnord 
'foobarfoobar' 

通過使用增強賦值,可讓程式碼更緊湊、更簡潔,同時在很多情況下的可讀性更強。

5.3 程式碼塊:縮排的樂趣