條件、迴圈及其他語句
條件、迴圈及其他語句
你現在肯定有點不耐煩了。這些資料型別確實好,可你卻沒法使用它們來做什麼,不是嗎?
下面加快點速度。你已見過幾種語句(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'
通過使用增強賦值,可讓程式碼更緊湊、更簡潔,同時在很多情況下的可讀性更強。