1 再談print及import
1.1 print
print函數(shù)的原型如下:print(arg1,arg2,…,sep=“具體分隔符”,end="具體結(jié)束符")
乳附。
- 默認情況下在使用print打印多個參數(shù)時呼巴,各個參數(shù)之間用空格隔開纹安;
- 在使用sep指定具體分隔符時,使用指定的分隔符來分割各個參數(shù);
- 默認情況下print語句的結(jié)束符為換行符,可以使用end來指定打印完各個百年來那個后的分隔符盾戴。
>>> print("hello","world")
hello world
>>> print("Age:",26)
Age: 26
>>> print("hello","world",sep="_")
hello_world
#未指定結(jié)束符時,默認以換行符結(jié)束
print("Hello","World")
print("Welcome","to","BeiJing")
E:\WorkDir\Python\venv\Scripts\python.exe E:/WorkDir/Python/test.py
Hello World
Welcome to BeiJing
#采用指定的結(jié)束符來結(jié)束
print("Hello","World",end="! ")
print("Welcome","to","BeiJing",end='.')
E:\WorkDir\Python\venv\Scripts\python.exe E:/WorkDir/Python/test.py
Hello World! Welcome to BeiJing.
Process finished with exit code 0
1.2 import導入時重命名
從模塊導入時兵多,通常使用import somemodule
或使用from somemodule import somefunction
或from somemodule import somefunction, anotherfunction, yetanotherfunction
或from somemodule import *
尖啡。僅當你確定要導入模塊中的一切時橄仆,采用使用最后一種方式。但如果有兩個模塊可婶,它們都包含函數(shù)open沿癞,該如何辦呢援雇?你可使用第一種方式導入這兩個模塊矛渴,并像下面這樣調(diào)用函數(shù):
module1.open(...)
module2.open(...)
但還有一種辦法:在語句末尾添加as子句并指定別名。下面是一個導入整個模塊并給它指定別名的例子:
>>> import math as foobar
>>> foobar.sqrt(4)
2.0
下面是一個導入特定函數(shù)并給它指定別名的例子:
>>> from math import sqrt as foobar
>>> foobar(4)
2.0
對于前面的函數(shù)open惫搏,可像下面這樣導入它們:
from module1 import open as open1
from module2 import open as open2
2 賦值
2.1 序列解包
賦值語句你見過很多具温,有的給變量賦值,還有的給數(shù)據(jù)結(jié)構的一部分(如列表中的元素和切片筐赔,或者字典項)賦值铣猩,但還有其他類型的賦值語句。例如茴丰,可同時(并行)給多個變量賦值:
>>> x, y, z = 1, 2, 3
>>> print(x, y, z)
1 2 3
看似用處不大达皿?看好了,使用這種方式還可交換多個變量的值贿肩。
>>> x, y = y, x
>>> print(x, y, z)
2 1 3
實際上峦椰,這里執(zhí)行的操作稱為序列解包(或可迭代對象解包):將一個序列(或任何可迭代對象)解包,并將得到的值存儲到一系列變量中汰规。下面用例子進行解釋汤功。
>>> values = 1, 2, 3
>>> values
(1, 2, 3)
>>> x,y, z = values
>>> x
1
這在使用返回元組(或其他序列或可迭代對象)的函數(shù)或方法時很有用。假設要從字典中隨便獲攘锵(或刪除)一個鍵-值對滔金,可使用方法popitem,它隨便獲取一個鍵-值對并以元組的方式返回茂嗓。接下來餐茵,可直接將返回的元組解包到兩個變量中。
>>> scoundrel = {'name': 'Robin', 'girlfriend': 'Marion'}
>>> key, value = scoundrel.popitem()
>>> key
'girlfriend'
>>> value
'Marion'
這讓函數(shù)能夠返回被打包成元組的多個值述吸,然后通過一條賦值語句輕松地訪問這些值钟病。
要解包的序列包含的元素個數(shù)必須與你在等號左邊列出的目標個數(shù)相同,否則Python將引發(fā)異常刚梭。
>>> x,y,z=1,2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
可使用星號運算符(*)來收集多余的值肠阱,這樣無需確保值和變量的個數(shù)相同,如下例所示:
>>> 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']
賦值語句的右邊可以是任何類型的序列屹徘,但帶星號的變量最終包含的總是一個列表。在變量和值的個數(shù)相同時亦如此衅金。
>>> a, *b, c = "abc"
>>> a, b, c
('a', ['b'], 'c')
這種收集方式也可用于函數(shù)參數(shù)列表中噪伊。
2.2 鏈式賦值
鏈式賦值是一種快捷方式簿煌,用于將多個變量關聯(lián)到同一個值。這有點像前一節(jié)介紹的并行賦值鉴吹,但只涉及一個值:
x = y = somefunction()
上述代碼與下面的代碼等價:
y = somefunction()
x = y
請注意姨伟,這兩條語句可能與下面的語句不等價:
x = somefunction()
y = somefunction()
有關這方面的詳細信息,請參閱5.4.6節(jié)介紹相同運算符(is)的部分豆励。
2.3 增強賦值
可以不編寫代碼x = x + 1
夺荒,而將右邊表達式中的運算符(這里是+)移到賦值運算符(=)的前面,從而寫成x += 1
良蒸。這稱為增強賦值技扼,適用于所有標準運算符,如*嫩痰、/剿吻、%等。
>>> x = 2
>>> x += 1
>>> x *= 2
>>> x
6
增強賦值也可用于其他數(shù)據(jù)類型(只要使用的雙目運算符可用于這些數(shù)據(jù)類型)串纺。
>>> fnord = 'foo'
>>> fnord += 'bar'
>>> fnord *= 2
>>> fnord
'foobarfoobar'
3 條件和條件語句
3.1 布爾表達式
用作布爾表達式(如用作if語句中的條件)時丽旅,下面的值都將被解釋器視為假:
False None 0 "" () [] {}
換而言之,標準值False和None纺棺、各種類型(包括浮點數(shù)榄笙、復數(shù)等)的數(shù)值0、空序列(如空字符串五辽、空元組办斑、空列表)以及空映射(如空字典)都被視為假,而其他各種值都被視為真(包括特殊值True)杆逗。
3.2 比較運算符
- 理論上乡翅,用<和<=等運算符可以比較任意兩個對象x和y的相對大小,并獲得一個真值罪郊,但這種比較僅在x和y的類型相同或相近時(如兩個整數(shù)或一個整數(shù)和一個浮點數(shù))才有意義蠕蚜。
- 在Python 3中,已經(jīng)不允許這樣比較不兼容的類型了悔橄,并且不允許對不兼容的類型進行操作(如將int與str相加等)靶累;
- ==用來檢查兩個對象是否相等,而is用來檢查兩個對象是否相同(是同一個對象)癣疟。
>>> x = y = [1, 2, 3]
>>> z = [1, 2, 3]
>>> x == y
True
>>> x == z
True
>>> x is y
True
>>> x is z
False
- 不要將is用于數(shù)和字符串等不可變的基本值挣柬。鑒于Python在內(nèi)部處理這些對象的方式,這樣做的結(jié)果是不可預測的睛挚。
>>> 10 is 10
True
>>> 10 is 11
False
>>>
>>>
>>> "hello" is "hello"
True
>>>
>>> "hello" is "world"
False
>>>
>>>
>>> x="hello"
>>> y="hello"
>>> x is y
True
>>>
>>>
>>> x=1
>>> y=1
>>> x is y
True
3.3 if..elif..else語句
if condition1:
語句1
語句2
…
elif condition2:
語句3
語句4
…
else:
語句5
語句6
…
3.4 assert關鍵字
assert condition,可選說明(在斷言為False而報出的錯誤中會進行說明)
>>> x=10
>>> assert x<100
>>> assert x<9,"x>=9"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: x>=9
4 循環(huán)語句
4.1 while循環(huán)
while condition:
語句1
語句2
……
例如:打印出 1-10的整數(shù)
x=1
while x<=10:
print(x,end=' ')
x+=1
4.2 for循環(huán)
while語句非常靈活邪蛔,可用于在條件為真時反復執(zhí)行代碼塊。這在通常情況下很好扎狱,但有時候你可能想根據(jù)需要進行定制侧到。一種這樣的需求是為序列(或其他可迭代對象)中每個元素執(zhí)行代碼塊勃教。
for para in sequence:
語句1
語句2
……
注意:
- 基本上,可迭代對象是可使用for循環(huán)進行遍歷的對象匠抗。后續(xù)將詳細介紹可迭代對象和迭代器故源。就目前而言,只需將可迭代對象視為序列即可汞贸。
- 可以使用
range(start,end)
來創(chuàng)建一個可迭代的范圍[start,end),或者使用range(end)
創(chuàng)建范圍[0,end)绳军。
>>> range(1,10)
range(1, 10)
>>> list(range(1,10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
例如:
words = ['this', 'is', 'an', 'ex', 'parrot']
for word in words:
print(word)
#或
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for number in numbers:
print(number)
#打印1-100之間的整數(shù)
for number in range(1,101):
print(number)
5 一些常用的迭代工具
5.1 zip并行迭代
有時候,你可能想同時迭代兩個序列著蛙。假設有下面兩個列表:
names = ['anne', 'beth', 'george', 'damon']
ages = [12, 45, 32, 102]
如果要打印名字和對應的年齡删铃,可以像下面這樣做:
for i in range(len(names)):
print(names[i], 'is', ages[i], 'years old')
i是用作循環(huán)索引的變量的標準名稱耳贬。一個很有用的并行迭代工具是內(nèi)置函數(shù)zip踏堡,它將兩個序列“縫合”起來,并返回一個由元組組成的序列咒劲。返回值是一個適合迭代的對象顷蟆,要查看其內(nèi)容,可使用list將其轉(zhuǎn)換為列表腐魂。
>>> list(zip(names, ages))
[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]
“縫合”后帐偎,可在循環(huán)中將元組解包。
for name, age in zip(names, ages):
print(name, 'is', age, 'years old')
函數(shù)zip可用于“縫合”任意數(shù)量的序列蛔屹。需要指出的是削樊,當序列的長度不同時,函數(shù)zip將在最短的序列用完后停止“縫合”兔毒。
>>> list(zip(range(5), range(100000000)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
5.2 使用enumerate同時遍歷索引和內(nèi)容
strings=['this','is','a','good','girl']
for index,context in enumerate(strings):
print(index,context)
#運行結(jié)果
0 this
1 is
2 a
3 good
4 girl
5.3 反向迭代和排序后再迭代
來看另外兩個很有用的函數(shù):reversed和sorted漫贞。它們類似于列表方法reverse和sort(sorted接受的參數(shù)也與sort類似),但可用于任何序列或可迭代的對象育叁,且不就地修改對象迅脐,而是返回反轉(zhuǎn)和排序后的版本。
>>> sorted([4, 3, 6, 8, 3])
[3, 3, 4, 6, 8]
>>> sorted('Hello, world!')
[' ', '!', ',', 'H', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
>>> list(reversed('Hello, world!'))
['!', 'd', 'l', 'r', 'o', 'w', ' ', ',', 'o', 'l', 'l', 'e', 'H']
>>> ''.join(reversed('Hello, world!'))
'!dlrow ,olleH'
請注意豪嗽,sorted返回一個列表谴蔑,而reversed像zip那樣返回一個更神秘的可迭代對象。你無需關心這到底意味著什么龟梦,只管在for循環(huán)或join等方法中使用它隐锭,不會有任何問題。只是你不能對它執(zhí)行索引或切片操作计贰,也不能直接對它調(diào)用列表的方法钦睡。要執(zhí)行這些操作,可先使用list對返回的對象進行轉(zhuǎn)換蹦玫。
5.4 跳出循環(huán):break赎婚,continue
要結(jié)束(跳出)循環(huán)刘绣,可使用break。假設你要找出小于100的最大平方值(整數(shù)與自己相乘的結(jié)果)挣输,可從100開始向下迭代纬凤。找到一個平方值后,無需再迭代撩嚼,因此直接跳出循環(huán)停士。
from math import sqrt
for n in range(99, 0, -1):
root = sqrt(n)
if root == int(root):
print(n)
break
使用continue
for x in seq:
if condition1: continue
if condition2: continue
if condition3: continue
do_something()
do_something_else()
do_another_thing()
etc()
while True...break示例
while True:
word = input('Please enter a word: ')
if not word: break
# 使用這個單詞做些事情:
print('The word was ', word)
5.5 和循環(huán)配套使用的else子句
在循環(huán)中添加的else子句,它僅在循環(huán)中沒有調(diào)用break時才執(zhí)行
from math import sqrt
for n in range(99, 81, -1):
root = sqrt(n)
if root == int(root):
print(n)
break
else: #在循環(huán)中添加的else子句完丽,它僅在循環(huán)中沒有調(diào)用break時才執(zhí)行
print("Didn't find it!")
6 各種推導式
6.1 列表推導
列表推導是一種從其他列表創(chuàng)建列表的方式恋技,類似于數(shù)學中的集合推導。列表推導的工作原理非常簡單逻族,有點類似于for循環(huán)蜻底。
>>> [x * x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
這個列表由range(10)內(nèi)每個值的平方組成,非常簡單吧聘鳞?如果只想打印那些能被3整除的平方值薄辅,該如何辦呢?可使用求模運算符:如果y能被3整除抠璃, y%3 將返回(請注意站楚,僅當x能被3整除時, x*x才能被3整除)搏嗡。為實現(xiàn)這種功能窿春,可在列表推導中添加一條if語句。
>>> [x*x for x in range(10) if x 3 == 0] %
[0, 9, 36, 81]
還可添加更多的for部分采盒。
>>> [(x, y) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
作為對比旧乞,下面的兩個for循環(huán)創(chuàng)建同樣的列表:
result = []
for x in range(3):
for y in range(3):
result.append((x, y))
與以前一樣,使用多個for部分時纽甘,也可添加if子句良蛮。
>>> girls = ['alice', 'bernice', 'clarice']
>>> boys = ['chris', 'arnold', 'bob']
>>> [b+'+'+g for b in boys for g in girls if b[0] == g[0]]
['chris+clarice', 'arnold+alice', 'bob+bernice']
這些代碼將名字的首字母相同的男孩和女孩配對。
上述代碼要遍歷所有的boys和girls悍赢,效率比較低决瞳,下面是一種更好的解決方案解決方案:
girls=['alice','bernice','clarice','apple']
boys=['chris','arnold','bob']
letterGirls={}
for girl in girls:
letterGirls.setdefault(girl[0],[]).append(girl)
print([b+'->'+g for b in boys for g in letterGirls[b[0]]])
#執(zhí)行結(jié)果:
['chris->clarice', 'arnold->alice', 'arnold->apple', 'bob->bernice']
這個程序創(chuàng)建一個名為letterGirls的字典,其中每項的鍵都是一個字母左权,而值為以這個字母開頭的女孩名字組成的列表(字典方法setdefault在前一章介紹過)皮胡。創(chuàng)建這個字典后,列表推導遍歷所有的男孩赏迟,并查找名字首字母與當前男孩相同的所有女孩屡贺。這樣,這個列表推導就無需嘗試所有的男孩和女孩組合并檢查他們的名字首字母是否相同了。
6.2 ()生成generator
將列表推導式的[]改成()即可得到生成器甩栈。
multiples = (i for i in range(30) if i % 3 is 0)
print(type(multiples))
# Output: <type 'generator'>
6.3 字典推導
字典推導和列表推導的使用方法是類似的泻仙,只不中括號該改成大括號。直接舉例說明:
例一:大小寫key合并
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {
k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
for k in mcase.keys()
if k.lower() in ['a','b']
}
print(mcase_frequency)
# Output: {'a': 17, 'b': 34}
例二:快速交換key和value
mcase = {'a': 10, 'b': 34}
mcase_frequency = {v: k for k, v in mcase.items()}
print(mcase_frequency)
# Output: {10: 'a', 34: 'b'}
6.4 集合推導式
它們跟列表推導式也是類似的量没。 唯一的區(qū)別在于它使用大括號{}玉转。集合推導式的結(jié)果中刪除了重復的元素。
>>> squared={x**2 for x in [1,1,2]}
>>> squared
{1, 4}
7 pass殴蹄、 del究抓、 exec和eval
- pass語句什么都不做,但適合用作占位符袭灯。
- del語句用于刪除變量或數(shù)據(jù)結(jié)構的成員刺下,但不能用于刪除值。
- 函數(shù)exec用于將字符串作為Python程序執(zhí)行稽荧。
- 函數(shù)eval計算用字符串表示的表達式并返回結(jié)果
7.1 exec
函數(shù)exec將字符串作為代碼執(zhí)行橘茉。
>>> exec("print('Hello, world!')")
Hello, world!
為了放置exec中執(zhí)行的程序污染代碼,在執(zhí)行exec函數(shù)時蛤克,可以向其傳遞一個命名空間捺癞。實際上夷蚊,可向exec提供兩個命名空間:一個全局的和一個局部的构挤。提供的全局命名空間必須是字典,而提供的局部命名空間可以是任何映射惕鼓。這一點也適用于eval筋现。
>>> from math import sqrt
#傳遞過來的sqrt變量和當前模塊中的sqrt函數(shù)重名
>>> exec("sqrt = 1")
>>> sqrt(4)
Traceback (most recent call last):
File "<pyshell#18>", line 1, in ?
sqrt(4)
TypeError: object is not callable: 1
#使用字典scope作為exec的命名空間
>>> from math import sqrt
>>> scope = {}
>>> exec('sqrt = 1', scope)
>>> sqrt(4)
2.0
>>> scope['sqrt']
1
7.2 eval
eval是一個類似于exec的內(nèi)置函數(shù)。 exec執(zhí)行一系列Python語句箱歧,而eval計算用字符串表示的Python表達式的值矾飞,并返回結(jié)果(exec什么都不返回,因為它本身是條語句)呀邢。
>>> eval(input("Enter an arithmetic expression: "))
Enter an arithmetic expression: 6 + 18 * 2
42