import的使用
語言的學習只有在不斷深入后才能進一步發(fā)現(xiàn)其中隱藏的驚人特性,即使是簡單的print函數(shù)朽砰,在不斷使用后也會發(fā)現(xiàn)更多使用方式,import將帶你進入一個更快捷的編程模式。
1 import語句
在講解import語句之前先看一個示例:
import math
r=5
print('半徑為5 的圓的面積為:%.2f' %(math.pi*r**2))
保存文件名為import_test.py瞧柔。在cmd命令窗口執(zhí)行如下命令:
D:\python\workspace>python import_test.py
半徑為5 的圓的面積為:78.54
上面的程序使用了import語句漆弄。
import math的意思為從Python標準庫中引入math.py模塊,這是Python中定義的引入模塊的方法造锅。import的標準語法如下:
import module1[, module2[,... moduleN]]
表示允許一個import導入多個模塊撼唾,但各個模塊間需要用逗號隔開。
當解釋器遇到import語句時备绽,如果模塊在當前搜索路徑就會被導入券坞。搜索路徑是一個解釋器鬓催,會先搜索所有目錄的列表肺素。
當我們使用import語句時,Python解釋器怎樣找到對應的文件呢宇驾?這涉及Python的搜索路徑倍靡,搜索路徑由一系列目錄名組成,Python解釋器會依次從這些目錄中尋找引入的模塊课舍∷鳎看起來很像環(huán)境變量,事實上可以通過定義環(huán)境變量的方式確定搜索路徑筝尾。搜索路徑是在Python編譯或安裝時確定的捡需,被存儲在sys模塊的path變量中。查看搜索路徑的方式如下:
import sys
print('Python 的搜索路徑為:%s' % sys.path)
保存文件名為import_sys.py筹淫,在cmd命令窗口執(zhí)行結(jié)果如下:
D:\python\workspace>python import_sys.py
Python的搜索路徑為:['D:\\python\\workspace', 'E:\\python\\pythoninstall\\python
35.zip', 'E:\\python\\pythoninstall\\DLLs', 'E:\\python\\pythoninstall\\lib', 'E:\\python\\pythoninstall',
'E:\\python\\pythoninstall\\lib\\site-packages']
由以上輸出結(jié)果看到站辉,sys.path輸出了一個列表,第一項輸出的是執(zhí)行文件所在的目錄损姜,即我們執(zhí)行Python解釋器的目錄(如果是腳本饰剥,就是運行腳本所在的目錄)。
了解搜索路徑的概念后摧阅,可以在腳本中修改sys.path引入一些不在搜索路徑中的模塊汰蓉。
上面我們初步引入了import語句,除了用import引入模塊外棒卷,還有另一種方式引入模塊顾孽,先看交互模式下輸入的示例:
>>> from math import pi
>>> print (pi)
3.141592653589793
上面的操作使用了from math import pi的方式,這是什么意思呢比规?
在Python中岩齿,from語句可以從模塊中導入指定部分到當前命名空間中,語法如下:
from modname import name1[, name2[, ... nameN]]
例如苞俘,from math import pi語句就是從math模塊中導入pi到當前命名空間盹沈,該語句不會將math整個模塊導入。比如在math模塊中還有sin、exp函數(shù)乞封,在這個語句里這兩個函數(shù)都使用不了做裙,而在導入整個math模塊的語句中可以使用。在交互模式下輸入:
>>> import math
>>> print(math.pi) #math.pi 可以被輸出
3.141592653589793
>>> print(math.sin(1)) #math.sin(1)可以被輸出
0.8414709848078965
>>> print(math.exp(1)) #math.exp(1)可以被輸出
2.718281828459045
>>> from math import pi
>>> print (pi) #pi 可以被輸出
3.141592653589793
>>> print(sin(1)) #sin(1)不可以被輸出
Traceback (most recent call last):
File "<pyshell#51>", line 1, in <module>
print(sin(1))
NameError: name 'sin' is not defined
>>> print(exp(1)) #exp(1)不可以被輸出
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
print(exp(1))
NameError: name 'exp' is not defined
由以上輸出結(jié)果可知肃晚,如果導入模塊锚贱,就會得到模塊中所有對象;如果指定導入某個對象关串,就只能得到該對象拧廊。
這樣做的好處是什么呢?先看如下示例:
>>> import math
>>> print(math.pi)
3.141592653589793
>>> print(pi)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
print(pi)
NameError: name 'pi' is not defined
>>> from math import pi
>>> print(pi)
3.141592653589793
由上面的輸出結(jié)果可知晋修,如果在導入math模塊時訪問pi對象吧碾,需要使用math.pi,直接使用pi訪問不了墓卦,會報錯倦春。使用import語句后,可以直接訪問pi對象落剪,不需要加上模塊名進行訪問睁本。
如果要訪問模塊中多個對象,是否需要一個一個導入呢忠怖?如果要訪問math中的pi和sin呢堰,是否要寫兩個from math import語句?例如:
from math import pi
from math import sin
當然不用凡泣,可以直接使用如下語句:
from math import pi,sin
可以從一個導入語句導入多個函數(shù)枉疼,多個函數(shù)之間用逗號分割。
如果要訪問模塊中多個對象问麸,是否需要一個一個導入呢往衷?當然不用,可以直接使用如下語句:
from math import *
使用該語句可以將math中所有對象都引入严卖,比如上面幾個報錯的情況就可以成功輸出結(jié)果了席舍,例如:
>>> from math import *
>>> print(pi) #pi可以被輸出
3.141592653589793
>>> print(sin(1)) #sin(1)可以被輸出
0.8414709848078965
>>> print(exp(1)) #exp(1)可以被輸出
2.718281828459045
由輸出結(jié)果看到,pi哮笆、sin来颤、exp等函數(shù)都可以被正確輸出了。這是一個簡單地將項目中所有模塊都導入的方法稠肘。在實際開發(fā)中福铅,這種聲明不建議過多使用,這樣不利于編寫清晰项阴、簡單的代碼滑黔。只有想從給定模塊導入所有功能時才使用這種方式。
除了上述幾種方式外,還可以為模塊取別名略荡,例如:
>>> import math as m
>>> m.pi
3.141592653589793
由輸出結(jié)果看到庵佣,給模塊取別名的方式為:在導出模塊的語句末尾增加一個as子句,as后面跟上別名名稱汛兜。
既然可以為模塊取別名巴粪,當然也可以為函數(shù)取別名,例如:
>>> from math import pi as p
>>> p
3.141592653589793
由輸出結(jié)果可知粥谬,我們?yōu)閜i取了別名為p肛根,為函數(shù)取別名的方式和為模塊取別名的方式類似,也是在語句后面加上as漏策,as后跟上別名名稱派哲。
2 使用逗號輸出
我們在前面的章節(jié)已經(jīng)看到許多使用逗號輸出的示例,例如:
>>> student='小智'
>>> print('學生稱呼:',student)
學生稱呼: 小智
這種方式還可以輸出多個表達式哟玷,只要將多個表達式用逗號隔開就行狮辽,例如:
>>> greeting='大家好一也!'
>>> intriduce='我叫小智巢寡,'
>>> comefrom='我來自智慧城市。'
>>> print(greeting,intriduce,comefrom)
大家好椰苟! 我叫小智抑月, 我來自智慧城市。
由輸出結(jié)果看到舆蝴,不使用格式化的方式也可以同時輸出文本和變量值谦絮。
別樣的賦值
之前我們介紹了很多賦值語句,在實際使用中洁仗,賦值語句還有很多特殊用法层皱,掌握這些用法對于提高編程水平很有幫助。
1 序列解包
前面已經(jīng)有不少賦值語句的示例赠潦,比如變量和數(shù)據(jù)結(jié)構(gòu)成員的賦值叫胖,不過賦值的方法不止這些,例如:
>>> x,y,z=1,2,3
>>> print(x,y,z)
1 2 3
由輸出結(jié)果看到她奥,可以多個賦值操作同時進行瓮增。后面再遇到對多個變量賦值時,就不需要對一個變量賦完值再對另一個變量賦值了哩俭,用一條語句就可以搞定绷跑,例如:
>>> x,y,z=1,2,3
>>> x,y=y,x
>>> print(x,y,z)
2 1 3
由輸出結(jié)果看到,x和y的值交換了凡资,所以可以交換兩個或多個變量的值砸捏。
在Python中,交換所做的事情叫作序列解包(sequence unpacking)或可選迭代解包,即將多個值的序列解開垦藏,然后放到變量序列中吩谦。可以通過下面的示例理解:
>>> nums=1,2,3
>>> nums
(1, 2, 3)
>>> x,y,z=nums
>>> x #獲得序列解開的值
1
>>> print(x,y,z)
1 2 3
由輸出結(jié)果看到膝藕,序列解包后式廷,變量獲得了對應的值。
再看另一個示例:
>>> student={'name':'小萌','number':'1001'}
>>> key,value=student.popitem()
>>> key
'number'
>>> value
'1001'
由輸出結(jié)果可知芭挽,此處作用于元組滑废,使用popitem方法將鍵-值作為元組返回,返回的元組可以直接賦值到兩個變量中袜爪。
序列解包允許函數(shù)返回一個以上的值并打包成元組蠕趁,然后通過一個賦值語句進行訪問。這里有一點要注意辛馆,解包序列中的元素數(shù)量必須和放置在賦值符號“=”左邊的數(shù)量完全一致俺陋,否則Python會在賦值時引發(fā)異常,例如:
>>> x,y,z=1,2,3
>>> x,y,z
(1, 2, 3)
>>> x,y,z=1,2
Traceback (most recent call last):
File "<pyshell#45>", line 1, in <module>
x,y,z=1,2
ValueError: not enough values to unpack (expected 3, got 2)
>>> x,y,z=1,2,3,4,5
Traceback (most recent call last):
File "<pyshell#46>", line 1, in <module>
x,y,z=1,2,3,4,5
ValueError: too many values to unpack (expected 3)
由以上輸出結(jié)果看到昙篙,當右邊的元素數(shù)量和左邊的變量數(shù)量不一致時腊状,執(zhí)行結(jié)果就會報錯。錯誤原因是沒有足夠的值解包(左邊變量多于右邊元素)或多個值未解包(左邊變量少于右邊元素)苔可。
謹記在操作序列解包時缴挖,要注意保證左邊和右邊數(shù)量的相等。
2 鏈式賦值
序列解包在對不同變量賦不同的值時非常有用焚辅,賦相同的值時用序列解包也可以實現(xiàn)映屋。其實還可以使用其他方法,如鏈式賦值(Chained Assignment同蜻,例如:
>>> x=y=z=10
>>> x
10
由輸出結(jié)果可知棚点,可以通過多個等式為多個變量賦同一個值,這種方法叫作鏈式賦值湾蔓。
鏈式賦值是將同一個值賦給多個變量瘫析。
上面的語句效果和下面的語句效果一樣:
>>> x=10
>>> y=x
>>> y
10
由輸出結(jié)果可知,既可以使用鏈式方式賦值卵蛉,也可以單獨賦值颁股,顯然鏈式方法更簡潔。
3 增量賦值
使用賦值運算符時沒有將表達式寫成類似x=x+1的形式傻丝,而是將表達式放置在賦值運算符(=)的左邊(如將x=x+1寫成x+=1)甘有,這種寫法在Python中叫作增量賦值(Augemented Assignment)。這種寫法對*(乘)葡缰、/(除)亏掀、%(取模)等標準運算符都適用忱反,例如:
>>> x=5
>>> x+=1 #加
>>> x
6
>>> x-=2 #減
>>> x
4
>>> x*=2 #乘
>>> x
8
>>> x/=4 #除
>>> x
2.0
由操作結(jié)果可以看到,使用增量賦值相對賦值操作看上去更簡潔滤愕。
增量賦值除了適用于數(shù)值類型温算,還適用于二元運算符的數(shù)據(jù)類型,例如:
>>> field ='Hello,'
>>> field += 'world'
>>> field
'Hello,world'
>>> field*=2
>>> field
'Hello,worldHello,world'
由操作結(jié)果可知间影,增量賦值操作也可以用于字符串注竿。
增量賦值可以讓代碼在很多情況下更易讀,也可以幫助我們寫出更緊湊魂贬、簡練的代碼巩割。
語句塊
語句塊并非一種語句,語句塊是一組滿足一定條件時執(zhí)行一次或多次的語句付燥。語句塊的創(chuàng)建方式是在代碼前放置空格縮進宣谈。
同一段語句塊中每行語句都要保持同樣的縮進,如果縮進不同键科,Python編譯器就會認為不屬于同一個語句塊或認為是錯誤的闻丑。
在Python中,冒號(:)用來標識語句塊的開始勋颖,語句塊中每一個語句都需要縮進(縮進量相同)嗦嗡。當退回到和已經(jīng)閉合的塊一樣的縮進量時,表示當前語句塊已經(jīng)結(jié)束了牙言。
條件語句
到目前為止酸钦,我們編寫的程序都是簡單地按語句順序一條一條執(zhí)行的怪得。那么將介紹讓程序選擇執(zhí)行語句的方法咱枉。
1 布爾變量的作用
布爾變量我們在第2章已經(jīng)有所接觸,第2章的運算符中多處提到的True徒恋、False就是布爾變量蚕断,布爾變量一般對應的是布爾值(也稱作真值,布爾值這個名字是根據(jù)對真值做過大量研究的George Boole命名的)入挣。
下面的值在作為布爾表達式時亿乳,會被解釋器看作假(false):
False None 0 "" () [] {}
換句話說,標準值False和None径筏、所有類型的數(shù)字0(包括浮點型葛假、長整型和其他類型)、空序列(如空字符串滋恬、空元組和空列表)以及空字典都為假聊训。其他值都為真,包括原生的布爾值True恢氯。
Python中所有值都能被解釋為真值带斑,這可能會讓你不太明白鼓寺,但理解這點非常有用。在Python中勋磕,標準的真值有True和False兩個妈候。在其他語言中,標準的真值為0(表示假)和1(表示真)挂滓。事實上苦银,True和False只不過是1和0的另一種表現(xiàn)形式,作用相同赶站,例如:
>>> True
True
>>> False
False
>>> True == 1
True
>>> False == 0
True
>>> True+False+2
3
由上面的輸出結(jié)果看到墓毒,在Python中,True和1等價亲怠,F(xiàn)alse和0等價所计。
布爾值True和False屬于布爾類型,bool函數(shù)可以用來轉(zhuǎn)換其他值团秽,例如:
>>> bool('good good study')
True
>>> bool('')
False
>>> bool(3)
True
>>> bool(0)
False
>>> bool([1])
True
>>> bool([])
False
>>> bool()
False
由輸出結(jié)果看到主胧,可以用bool函數(shù)做boolean值轉(zhuǎn)換。
因為所有值都可以用作布爾值(真值)习勤,所以幾乎不需要對它們進行顯式轉(zhuǎn)換踪栋,Python會自動轉(zhuǎn)換這些值。
注意:盡管[]和""都為假图毕,即bool([])==bool("")==False夷都,不過它們本身不相等,即[]!=""予颤。其他不同類型的假值也是如此囤官,如()!=False。
2 if語句
真值可以聯(lián)合使用蛤虐,首先看如下代碼:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
#if 基本用法
greeting='hello'
if greeting == 'hello':
print('hello')
該示例執(zhí)行結(jié)果如下:
hello
該示例為if條件執(zhí)行語句的一個實現(xiàn)示例党饮。如果條件(在if和冒號之間的表達式)判定為真,后面的語句塊(本例中是print語句)就會被執(zhí)行驳庭;如果條件判定為假刑顺,語句塊就不會被執(zhí)行。
上述示例代碼的執(zhí)行過程如圖所示饲常。
圖中的小黑點為if語句的起點蹲堂,往后執(zhí)行到條件語句(條件語句如greeting=='hello'),如果條件為真贝淤,就執(zhí)行條件代碼柒竞,然后結(jié)束這個if條件語句;如果條件為假霹娄,就跳過這段條件代碼能犯,這個if條件語句直接結(jié)束鲫骗。
在if語句塊中還可以執(zhí)行一些復雜操作,例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
#if 基本用法
greeting='hello'
if greeting == 'hello':
student={'小萌': '1001', '小智': '1002', '小強': '1005','小張': '1006'}
print('字典元素個數(shù)為:%d 個' % len(student))
student.clear()
print('字典刪除后元素個數(shù)為:%d 個' % len(student))
以上程序執(zhí)行結(jié)果為:
字典元素個數(shù)為:4 個
字典刪除后元素個數(shù)為:0 個
此處的if語句塊由多條語句組成踩晶,編寫過程中要注意保持語句的縮進一致执泰,否則在執(zhí)行時會報錯。
if語句的條件判定除了使用==外渡蜻,還可以使用>(大于)术吝、<(小于)、>=(大于等于)茸苇、<=(小于等于)等條件符表示大小關系排苍。除此之外,還可以使用各個函數(shù)或方法返回值作為條件判定学密。使用條件符的操作和使用==一樣淘衙,使用函數(shù)或表達式的操作在會逐步介紹。
提示:在練習過程中腻暮,要習慣編寫示例中開頭兩行的寫法彤守,即習慣寫以下兩行代碼:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
習慣寫這兩行代碼可以幫助你在代碼移植和編碼問題上避免很多問題。代碼移植時哭靖,如果從Windows移植到Linux系統(tǒng)上具垫,就必須加上第一行代碼。代碼中有中文時试幽,如果不加第二行筝蚕,就很容易出現(xiàn)亂碼的情況。
3 else子句
在if語句的示例中铺坞,當greeting的值為hello時起宽,if后面的條件執(zhí)行結(jié)果為true,進入下面的語句塊中執(zhí)行相關語句康震。如果greeting的值不是hello燎含,就不能進入語句塊,如果想顯示相關提示腿短,比如告訴我們greeting的值不為hello或執(zhí)行的不是if中的語句塊,該怎么辦呢绘梦?例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
greeting='hi'
if greeting == 'hello':
print('hello')
else:
print('該語句塊不在if 中橘忱,greeting 的值不是hello')
這段程序加入了一個新條件子句——else子句。之所以叫子句卸奉,是因為else不是獨立語句钝诚,只能作為if語句的一部分。使用else子句可以增加一種選擇榄棵。
該程序的輸出結(jié)果如下:
該語句塊不在if 中凝颇,greeting 的值不是hello
由輸出結(jié)果看到潘拱,if語句塊沒有被執(zhí)行,執(zhí)行的是else子句中的語句塊拧略。同if語句一樣芦岂,else子句中的語句塊也可以編寫復雜語句。
注意:在else子句后面沒有條件判定垫蛆。
4 elif子句
在else子句的示例中禽最,如果除if條件外,還有多個子條件需要判定袱饭,該怎么辦呢川无?
Python為我們提供了一個elif語句,elif是else if的簡寫虑乖,意思為具有條件的else子句懦趋,例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
num = 10
if num > 10:
print('num 的值大于10')
elif 0<=num<=10:
print('num 的值介于0 到10 之間')
else:
print('num 的值小于0')
由以上程序可知,elif需要和if疹味、else子句聯(lián)合使用愕够,不能獨立使用,并且必須以if語句開頭佛猛,可以選擇是否以else子句結(jié)尾惑芭。
程序輸出結(jié)果如下:
num的值介于0 到10 之間
由輸出結(jié)果得知,這段程序執(zhí)行的是elif子句中的語句塊继找,即elif子句的條件判定結(jié)果為true遂跟,所以執(zhí)行這個子句后的語句塊。
5 嵌套代碼塊
我們前面講述了if語句婴渡、else子句幻锁、elif子句,這幾個語句可以進行條件的選擇判定边臼,不過我們在實際項目開發(fā)中經(jīng)常需要一些更復雜的操作哄尔,例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
num = 10
if num%2==0:
if num%3==0:
print ("你輸入的數(shù)字可以整除 2 和 3")
elif num%4==0:
print ("你輸入的數(shù)字可以整除 2 和 4")
else:
print ("你輸入的數(shù)字可以整除 2,但不能整除 3 和 4")
else:
if num%3==0:
print ("你輸入的數(shù)字可以整除 3柠并,但不能整除 2")
else:
print ("你輸入的數(shù)字不能整除 2 和 3")
由上面的程序可知岭接,在if語句的語句塊中還存在if語句、語句塊以及else子句臼予,else子句的語句塊中也存在if語句和else子句鸣戴。
上面的程序輸出結(jié)果如下:
你輸入的數(shù)字可以整除 2,但不能整除 3 和 4
由輸出結(jié)果可以看出粘拾,執(zhí)行的是if語句塊中else子句的語句塊窄锅。
在Python中,該示例使用的這種結(jié)構(gòu)的代碼稱作嵌套代碼缰雇。所謂嵌套代碼入偷,是指把if追驴、else、elif等條件語句再放入if疏之、else殿雪、elif條件語句塊中,作為深層次的條件判定語句体捏。
6 更多操作
我們簡單介紹過一些運算符冠摄,現(xiàn)在將對其中一些涉及條件運算的運算符做進一步講解。
1. is:同一性運算符
is運算符比較有趣。我們先看如下程序:
>>> x=y=[1,2,3]
>>> z=[1,2,3]
>>> x==y
True
>>> x==z
True
>>> x is y
True
>>> x is z
False
在最后一個輸出語句之前,一切看起來非常美好躯概,都在意料中,不過最后一個語句卻出現(xiàn)了問題拆挥,為什么x和z相等卻不相同呢?
這是因為is運算符用于判定同一性而不是相等性某抓。變量x和y被綁定在同一個列表上纸兔,而變量z被綁定在另一個具有相同數(shù)值和順序的列表上。它們的值可能相等否副,卻不是同一個對象汉矿。
也可以從內(nèi)存的角度思考,即它們所指向的內(nèi)存空間不一樣备禀,x和y指向同一塊內(nèi)存空間洲拇,z指向另一塊內(nèi)存空間。
是不是看起來有些不可理喻曲尸,再看如下示例:
>>> x=[1,2,3]
>>> y=[1,5]
>>> x is not y
True
>>> del x[2]
>>> x
[1, 2]
>>> y[1]=2
>>> y
[1, 2]
>>> x==y
True
>>> x is y
False
在上面的程序中赋续,列表x和y一開始是不同的列表,后面將列表值更改為相等另患,但還是兩個不同的列表纽乱,即兩個列表值相等卻不等同。
綜上所述昆箕,使用==運算符判定兩個對象是否相等鸦列,使用is判定兩個對象是否等同(是否為同一對象)。
提示:盡量避免用is運算符比較數(shù)值和字符串這類不可變值为严。由于Python內(nèi)部操作這些對象方式的原因敛熬,使用is運算符的結(jié)果是不可預測的,除非你對堆棧有一定熟悉程度第股,否則很難預測運算結(jié)果。
2. 比較字符串和序列
字符串可以按照字母排列順序進行比較话原,我們在前面的章節(jié)已經(jīng)介紹過夕吻。這里介紹其他序列的比較操作诲锹。
其他序列比較的不是字符而是元素的其他類型,例如:
>>> [1,2]<[2,1]
True
>>> [1,2]<[1,2]
False
>>> [1,2]==[1,2]
True
由操作結(jié)果可知涉馅,也可以對列表進行比較操作归园。
如果一個序列中包括其他序列元素,比較規(guī)則也適用于序列元素稚矿,例如:
>>> [2,[1,2]]<[2,[1,3]]
True
由操作結(jié)果看到庸诱,也可以對嵌套列表進行比較操作。
3. 布爾運算符
前面我們已經(jīng)講述過不少布爾運算的操作晤揣。不過有時要檢查一個以上的條件桥爽,如果按照前面的操作方式,就會多走一些彎路昧识,例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
num = 10
if num <= 10:
if num>=5:
print('num的值介于5 到10 之間')
else:
print('num的值不介于5 到10 之間')
else:
print('num 的值不介于5 到10 之間')
上面的程序在寫法上沒什么問題钠四,但是走了一些不必要的彎路,可以將代碼編寫得更簡潔:
if num <= 10 and num>=5:
print('num 的值介于5 到10 之間')
else:
print('num 的值不介于5 到10 之間')
或者:
if 5 <= num <= 10:
print('num 的值介于5 到10 之間')
else:
print('num 的值不介于5 到10 之間')
上面的程序明顯更加簡潔跪楞、易讀缀去。
and運算符用于連接兩個布爾值,并在兩者都為真時返回真甸祭,否則返回假缕碎。與and同類的還有or和not兩個運算符。
布爾運算符有一個有趣的特性:只有在需要求值時才求值池户。舉例來說咏雌,表達式x and y需要兩個變量都為真時才為真,所以如果x為假煞檩,表達式就立刻返回false处嫌,無論y的值是多少。實際上斟湃,如果x為假熏迹,表達式就會返回x的值,否則返回y的值凝赛。這種行為被稱為短路邏輯(short-circuit logic)或惰性求值(lazy evaluation)注暗。布爾運算符通常被稱為邏輯運算符,這種行為同樣適用于or墓猎。在表達式x or y中捆昏,x為真時直接返回x的值,否則返回y值毙沾。注意骗卜,這意味著在布爾運算符后面的代碼都不會被執(zhí)行。
7 斷言
在Python中,有一個和if語句工作方式非常相近的關鍵字寇仓,其工作方式類似如下偽代碼:
if not condition:
crash program
在Python中為什么需要這樣的代碼呢举户?
在沒完善一個程序之前,我們不知道程序會在哪里出錯遍烦,與其在運行時崩潰俭嘁,不如在出現(xiàn)錯誤條件時就崩潰。一般來說服猪,可以要求一些條件必須為真供填。在Python中,assert關鍵字能實現(xiàn)這種工作方式罢猪。先來看一個示例:
>>> x=3
>>> assert x > 0, "x is not zero or negative"
>>> assert x%2 == 0, "x is not an even number" #提示x 不是偶數(shù)
Traceback (most recent call last):
File "<pyshell#81>", line 1, in <module>
assert x%2 == 0, "x is not an even number"
AssertionError: x is not an even number
由上面的輸出結(jié)果看到近她,當assert后面的條件為真時,程序正常運行坡脐;當assert后面的條件為假時泄私,輸出錯誤信息。錯誤的提示信息由我們自己定義备闲,這個錯誤提示信息可以稱為異常參數(shù)晌端。assert的異常參數(shù)是在斷言表達式后添加的字符串信息,用來解釋斷言并更容易知道問題出在哪里恬砂。
使用assert斷言是學習Python的好習慣咧纠,Python assert斷言句語格式及用法很簡單。
使用assert斷言時泻骤,要注意以下幾點:
(1)assert斷言用來聲明某個條件是真的漆羔。
(2)如果你非常確信你使用的列表中至少有一個元素,想要檢驗這一點狱掂,并在它非真時引發(fā)一個錯誤演痒,那么assert語句是應用在這種情形下的理想語句。
(3)assert語句失敗時趋惨,會引發(fā)一個AssertionError鸟顺。
循環(huán)
程序在一般情況下是按順序執(zhí)行的。編程語言提供了各種控制結(jié)構(gòu)器虾,允許更復雜的執(zhí)行路徑讯嫂。循環(huán)語句允許我們多次執(zhí)行一個語句或語句組。圖6-6所示為大多數(shù)編程語言中循環(huán)語句的執(zhí)行流程兆沙。
我們已經(jīng)知道條件為真(或假)時程序如何執(zhí)行了欧芽。若想讓程序重復執(zhí)行,該怎么辦呢葛圃?比如輸出1~100所有數(shù)字千扔,是寫100個輸出語句嗎憎妙?顯然你不想這樣做。接下來我們學習如何解決這個問題昏鹃。
1 while循環(huán)
我們先看如何使用簡單的程序輸出1~100所有數(shù)字尚氛,程序如下:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
n=1
while n<=100:
print('當前數(shù)字是:',n)
n += 1
由輸入程序看到洞渤,只需短短幾行就可以實現(xiàn)這個功能属瓣,我們看輸出結(jié)果(由于全部輸出會太長载迄,也沒有必要,此處顯示幾行輸出結(jié)果作為展示):
當前數(shù)字是: 1
當前數(shù)字是: 2
當前數(shù)字是: 3
當前數(shù)字是: 4
當前數(shù)字是: 5
……
由輸出結(jié)果看到抡蛙,按順序輸出了對應結(jié)果护昧。
該示例中使用了while關鍵字。在Python編程中粗截,while語句用于循環(huán)執(zhí)行程序惋耙,以處理需要重復處理的任務⌒懿基本語法形式為:
while 判斷條件:
執(zhí)行語句……
執(zhí)行語句可以是單個語句或語句塊绽榛。判斷條件可以是任何表達式,所有非零婿屹、非空(null)的值都為真(true)灭美。當判斷條件為假(false)時,循環(huán)結(jié)束昂利。
該流程圖的意思為:首先對while條件判定届腐,當條件為true時,執(zhí)行條件語句塊蜂奸,執(zhí)行完語句塊再判定while條件犁苏,若仍然為true,則繼續(xù)執(zhí)行語句塊扩所,直到條件為false時結(jié)束循環(huán)围详。
2 for循環(huán)
上面講述了while循環(huán),可以看到while語句非常靈活碌奉。例如以下代碼:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
n=0
fields=['a','b','c']
while n<len(fields):
print('當前字母是:',fields[n])
n += 1
該代碼實現(xiàn)的功能是將列表中的元素分別輸出短曾。該程序的實現(xiàn)沒有什么問題赐劣,我們是否有更好的方式實現(xiàn)這個功能呢?答案是有婉徘,例如:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
fields=['a','b','c']
for f in fields:
print('當前字母是:',f)
可以看到,代碼比前面使用while循環(huán)時更簡潔盖呼,代碼量也更少。程序執(zhí)行輸出結(jié)果如下:
當前字母是: a
當前字母是: b
當前字母是: c
該示例使用了for關鍵字约炎。在Python中蟹瘾,for關鍵字叫做for循環(huán),for循環(huán)可以遍歷任何序列的項目狸捕,如一個列表或字符串众雷。for循環(huán)的語法格式如下:
for iterating_var in sequence:
statements(s)
sequence是任意序列,iterating_var是序列中需要遍歷的元素鸡岗。statements是待執(zhí)行的語句塊纯蛾。
for循環(huán)的執(zhí)行流程如圖所示。
該流程圖的意思為:首先對for條件判定炮姨,游標(后面會詳細講解這個詞)指向第0個位置舒岸,即指向第一個元素芦圾,看sequence序列中是否有元素,若有洪乍,則將元素值賦給iterating_var夜焦,接著執(zhí)行語句塊,若語句塊中需要獲取元素值巷波,則使用iterating_var的值,執(zhí)行完語句塊后抹镊,將序列的游標往后挪一個位置,再判定該位置是否有元素颈渊,若仍然有元素氨菇,則繼續(xù)執(zhí)行語句塊,然后序列的游標再往后挪一個位置查蓉,直到下一個位置沒有元素時結(jié)束循環(huán)豌研。
我們再看以下示例:
#! /usr/bin/python3
# -*- coding:UTF-8 -*-
print('-----for 循環(huán)字符串-----------')
for letter in 'good': #for 循環(huán)字符串
print ('當前字母 :', letter)
print('-----for 循環(huán)數(shù)字序列-----------')
number=[1,2,3]
for num in number: #for 循環(huán)數(shù)字序列
print('當前數(shù)字:',num)
print('-----for 循環(huán)字典-----------')
tups={'name':'小智','number':'1002'}
for tup in tups: #for 循環(huán)字典
print('%s:%s' % (tup,tups[tup]))
輸出結(jié)果如下:
-----for 循環(huán)字符串-----------
當前字母 : g
當前字母 : o
當前字母 : o
當前字母 : d
-----for 循環(huán)數(shù)字序列-----------
當前數(shù)字: 1
當前數(shù)字: 2
當前數(shù)字: 3
-----for 循環(huán)字典-----------
number:1002
name:小智
由上面的輸入代碼和輸出結(jié)果可以看到唬党,for循環(huán)的使用還是比較方便的。
提示:如果能使用for循環(huán)霜浴,就盡量不要使用while循環(huán)阴孟。
3 循環(huán)遍歷字典元素
在上面的示例中我們已經(jīng)提供了使用for循環(huán)遍歷字典的代碼税迷,代碼如下:
tups={'name':'小智','number':'1002'}
for tup in tups: #for 循環(huán)字典
print('%s:%s' % (tup,tups[tup]))
可以看到,此處用for循環(huán)對字典的處理看起來有一些繁雜慕嚷,是否可以使用更直觀的方式處理字典呢毕泌?
還記得我們前面學習的序列解包嗎?for循環(huán)的一大好處是可以在循環(huán)中使用序列解包挠说,例如:
tups={'name':'小智','number':'1002'}
for key,value in tups.items():
print('%s:%s' % (key,value))
輸出結(jié)果如下:
number:1002
name:小智
由輸入代碼和輸出結(jié)果看到坎弯,可以使用items方法將鍵-值對作為元組返回译暂。
注意:字典中的元素是沒有順序的外永。也就是說拧咳,迭代時字典中的鍵和值都能保證被處理,但是處理順序不確定祭衩。這也是用for循環(huán)輸出字典中的元素時不按照順序輸出的原因阅签。
4 迭代工具
在Python中,迭代序列或其他可迭代對象時路克,有一些函數(shù)非常有用养交。下面我們介紹一些有用的函數(shù)。
1. 并行迭代
程序可以同時迭代兩個序列灰羽,輸入如下:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
student=['xiaomeng','xiaozhi','xiaoqiang']
number=[1001,1002,1003]
for i in range(len(student)):
print(student[i],'的學號是:',number[i])
程序執(zhí)行結(jié)果如下:
xiaomeng 的學號是:1001
xiaozhi 的學號是:1002
xiaoqiang 的學號是:1003
在程序中廉嚼,i是循環(huán)索引的標準變量名座每。
在Python中,內(nèi)建的zip函數(shù)用來進行并行迭代舰绘,可以把兩個序列合并在一起葱椭,返回一個元組的列表,例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
student=['xiaomeng','xiaozhi','xiaoqiang']
number=[1001,1002,1003]
for name,num in zip(student,number):
print(name,'的學號是:',num)
程序執(zhí)行結(jié)果和前面一樣秦陋。
zip函數(shù)可以作用于任意數(shù)量的序列治笨,并且可以應付不等長的序列赤嚼,當短序列“用完”時就會停止更卒。
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
for num1,num2 in zip(range(3),range(100)):
print('zip 鍵值對為:',num1,num2)
程序執(zhí)行結(jié)果如下:
zip 鍵值對為: 0 0
zip 鍵值對為: 1 1
zip 鍵值對為: 2 2
由輸出結(jié)果看到稚照,zip函數(shù)以短序列為準,當短序列遍歷結(jié)束時上枕,for循環(huán)就會遍歷結(jié)束辨萍。
提示:此處用到range函數(shù)斤彼,是Python 3中的函數(shù),在Python 2版本中存在與這個函數(shù)功能類似的xrange函數(shù)。
2. 翻轉(zhuǎn)和排序迭代
我們在列表中學習過reverse和sort方法悦施,此處介紹兩個類似的函數(shù)——reversed和sorted函數(shù)。這兩個函數(shù)可作用于任何序列或可迭代對象穷蛹,但不是原地修改對象昼汗,而是返回翻轉(zhuǎn)或排序后的版本。在交互模式下輸入:
>>> sorted([5,3,7,1])
[1, 3, 5, 7]
>>> sorted('hello,world!')
['!', ',', 'd', 'e', 'h', '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'
由輸出結(jié)果我們看到蛙吏,sorted函數(shù)返回的是一個列表鞋吉,reversed函數(shù)返回的是一個可迭代對象。它們的具體含義不用過多關注泼诱,在for循環(huán)和join方法中使用不會有任何問題赊锚。如果要對這兩個函數(shù)使用索引屉栓、分片及調(diào)用list方法友多,就可以使用list類型轉(zhuǎn)換返回對象句灌。
5 跳出循環(huán)
我們在前面的示例中講過,循環(huán)會一直執(zhí)行骗绕,直到條件為假或序列元素用完時才會結(jié)束资昧。若我們想提前中斷循環(huán),比如循環(huán)的結(jié)果已經(jīng)是我們想要的了撤缴,不想讓循環(huán)繼續(xù)執(zhí)行而占用資源叽唱,有什么方法可以實現(xiàn)呢?
Python提供了break虎眨、continue等語句可用于這種情形镶摘。
1. break
break語句用來終止循環(huán)語句,即使循環(huán)條件中沒有False條件或序列還沒有遍歷完凄敢,也會停止執(zhí)行循環(huán)語句。
break語句用在while和for循環(huán)中扑庞。
如果使用嵌套循環(huán)俊卤,break語句就會停止執(zhí)行最深層的循環(huán)消恍,并開始執(zhí)行下一行代碼。
break語句語法如下:
break
break語句的執(zhí)行流程如圖所示约啊。
當遇到break語句時,無論執(zhí)行什么條件记盒,都跳出這個循環(huán)外傅,例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
for letter in 'hello': #示例1
if letter == 'l':
break
print ('當前字母為:', letter)
num = 10 #示例2
while num > 0:
print ('輸出數(shù)字為:', num)
num -= -1
if num == 8:
break
輸出結(jié)果如下:
當前字母為: h
當前字母為: e
輸出數(shù)字為: 10
輸出數(shù)字為: 9
[圖片上傳失敗...(image-c5ab9b-1567490535468)]
圖6-10 continue執(zhí)行流程
由輸出結(jié)果看到,在示例1中碾盟,輸出語句輸出循環(huán)遍歷到的字符技竟,當遇到指定字符時,跳出for循環(huán)熙尉。在示例2中搓扯,使用while做條件判定,在語句塊中輸出滿足條件的數(shù)字攀细,當數(shù)字等于8時爱态,跳出while循環(huán)境钟,不再繼續(xù)遍歷。
2. continue
continue語句用來告訴Python跳過當前循環(huán)的剩余語句慨削,然后繼續(xù)進行下一輪循環(huán)。
continue語句用在while和for循環(huán)中磁椒。
continue語句的語法格式如下:
continue
continue語句的執(zhí)行流程如圖所示浆熔。
當執(zhí)行過程中遇到continue語句時桥帆,無論執(zhí)行條件是真還是假慎皱,都跳過這次循環(huán)茫多,進入下一次循環(huán)忽刽,例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
for letter in 'hello': # 示例1
if letter == 'l':
continue
print ('當前字母 :', letter)
num = 3 # 示例2
while num > 0:
num -= 1
if num == 2:
continue
print ('當前變量值 :', num)
輸出結(jié)果如下:
當前字母 : h
當前字母 : e
當前字母 : o
當前變量值 : 1
當前變量值 : 0
由輸出結(jié)果看到,相比于break語句今膊,使用continue語句只是跳過一次循環(huán)歉甚,不會跳出整個循環(huán)。
6 循環(huán)中的else子句
在開發(fā)過程中纸泄,可能需要在while、for等循環(huán)不滿足條件時做一些工作雪营。該怎么實現(xiàn)呢?下面進行介紹衡便。
1. 在while循環(huán)中使用else 語句
在while條件語句為false時,執(zhí)行else的語句塊谴餐,例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
num = 0
while num < 3:
print (num, " 小于 3")
num = num + 1
else:
print (num, " 大于或等于 3")
print("結(jié)束循環(huán)!")
執(zhí)行結(jié)果如下:
0 小于 3
1 小于 3
2 小于 3
3 大于或等于 3
結(jié)束循環(huán)!
由輸出結(jié)果看到岂嗓,while循環(huán)結(jié)束后執(zhí)行了else語句中的語句塊鹊碍,輸出“3大于或等于3”語句。
2. 在for 循環(huán)中使用else 語句
在for條件語句為false或結(jié)束后沒有被break中斷時侈咕,執(zhí)行else的語句塊耀销,例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
names = ['xiaomeng', 'xiaozhi']
for name in names:
if name == "xiao":
print("名稱:",name)
break
print("循環(huán)名稱列表 " + name)
else:
print("沒有循環(huán)數(shù)據(jù)!")
print("結(jié)束循環(huán)!")
程序執(zhí)行結(jié)果如下:
循環(huán)名稱列表 xiaomeng
循環(huán)名稱列表 xiaozhi
沒有循環(huán)數(shù)據(jù)!
結(jié)束循環(huán)!
由輸出條件看到,for循環(huán)結(jié)束后執(zhí)行了else語句塊中的內(nèi)容摩桶。
pass語句
Python中的pass是空語句,作用是保持程序結(jié)構(gòu)的完整性硝清。pass語句的語法格式如下:
pass
pass不做任何事情,只是占位語句士飒,例如:
>>> pass
>>>
輸出結(jié)果什么都沒有做蔗崎。
為什么使用一個什么都不做的語句呢?再來看如下代碼:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
name='xiaomeng'
if name == 'xiaomeng':
print('hello')
elif name == 'xiaozhi':
#預留芳撒,先不做任何處理
else:
print('nothing')
執(zhí)行程序笔刹,結(jié)果如下:
File "itertor.py", line 63
else:
^
IndentationError: expected an indented block
執(zhí)行報錯了舌菜,因為程序中有空代碼亦镶,在Python中空代碼是非法的。解決辦法是在語句塊中加一個pass語句爱咬。上面的代碼更改為:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
name='xiaomeng'
if name == 'xiaomeng':
print('hello')
elif name == 'xiaozhi':
#預留台颠,先不做任何處理
pass
else:
print('nothing')
再執(zhí)行這段代碼勒庄,得到結(jié)果如下:
hello
輸出結(jié)果可以正確執(zhí)行了实蔽。
8 牛刀小試——猜字游戲編寫
為鞏固學習內(nèi)容局装,設計一個小游戲幫助我們系統(tǒng)地溫習本章的知識點。
游戲內(nèi)容是這樣的:隨便給定一個在一定范圍內(nèi)的數(shù)字拨脉,讓用戶去猜這個數(shù)字是多少玫膀,并輸入自己猜測的數(shù)字爹脾,系統(tǒng)判斷是否為給定數(shù)字灵妨。如果輸入的猜測數(shù)字大于給定值,提示你輸入的值大了泌霍;如果輸入的值小于給定值,就提示輸入的值小了蟹地;如果等于給定數(shù)字锈津,就提示你猜對了凉蜂,并展示猜了多少次猜中了。
在看參考代碼之前先思考一下茎杂,要實現(xiàn)這個小游戲煌往,你會怎么做呢轧邪?
思考點撥:
先從最簡單的方向思考,有3種情況:
(1)輸入值小于給定值曲管。
(2)輸入值等于給定值院水。
(3)輸入值大于給定值。
對于情況(1)和(3)檬某,需要繼續(xù)輸入;對于情況(2)民傻,輸入結(jié)束饰潜。
需要提供3個變量:一個變量用于記錄給定值和簸,一個變量用于記錄輸入值,一個變量用于記錄輸入了多少次薯酝,注意輸入次數(shù)至少是一次吴菠。
參考代碼如下(參考代碼對輸入元素是否為數(shù)字做了判斷浩村,同時判斷了輸入數(shù)字是否超出給定的數(shù)值范圍):
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
import random
number = random.randint(1,100)
guess = 0
while True:
num_input = input("請輸入一個1 到100 的數(shù)字:")
guess +=1
if not num_input.isdigit():
print ("請輸入數(shù)字心墅。")
elif int(num_input)<0 or int(num_input)>=100:
print ("輸入的數(shù)字必須介于1 到100。")
else:
if number==int(num_input):
print ("恭喜您瘫筐,您猜對了策肝,您總共猜了 %d 次"%guess)
break
elif number>int(num_input):
print ("您輸入的數(shù)字小了隐绵。")
elif number<int(num_input):
print ("您輸入的數(shù)字大了。")
else:
print ("系統(tǒng)發(fā)生不可預測問題酝枢,請聯(lián)系管理人員進行處理帘睦。
9 Python程序調(diào)試
這里通過設置的一些錯誤讓讀者認識在編寫代碼過程中的常見問題竣付,以幫助讀者熟悉和解決實際遇到的問題滞欠。
(1)在交互模式下輸入false,看會輸出什么結(jié)果逸绎,并嘗試解答為什么輸出這樣的結(jié)果棺牧。輸入true朗儒、true+false呢?
>>> false
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
false
NameError: name 'false' is not defined
(2)在while或for循環(huán)中乏悄,嘗試不對齊循環(huán)語句塊中的語句檩小,看看執(zhí)行結(jié)果是怎樣的?例如:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
num = 10
while num > 0:
print ('輸出數(shù)字為:', num)
num -= 1 #本行與其他行不對齊
if num == 8:
break
運行這段代碼规求,查看輸出結(jié)果是怎樣的颓哮,并嘗試更改為for循環(huán)鸵荠,再次查看結(jié)果蛹找。
(3)嘗試以下程序的執(zhí)行結(jié)果:
#! /usr/bin/python3
#-*- coding:UTF-8 -*-
name='xiaomeng'
if name == 'xiaomeng':
print('hello')
elif name == 'xiaozhi':
print('do nothing')
pass
else:
print('nothing')