while語句,提供了編寫通用循環的一種方法,而for語句是用來遍歷序列對象內的元素,並對每一個元素運行一個代碼塊。break,continue用在循環內,跳出整個循環或者跳出一次循環。
1、while循環
一、通常格式
格式:首行以及測試表達式,有一列或多列縮進語句的主體以及一個選用的else部分(控制權離開循環時而沒有碰到break語句時會執行)
python會一直計算開投的測試,而後執行循環主體內的語句,直到測試返回假值爲止。
while <test>:
<statements1>
else:
<statements2>
二、例子
>>> while True:
... print "Type Ctrl+C to stop!"
>>> while x:
... print x,
... x=x[1:]
...
diege iege ege ge e
注意 print末尾的逗號,會使全部輸出都出如今同一行。
>>> a,b=0,10
>>> while a<b:
... print a,
... a+=1
...
0 1 2 3 4 5 6 7 8 9
Python並無其餘語言中所謂的"do until」循環語句,不過咱們能夠在循環主體底部以一個測試和break來實現相似的功能。
while True:
do something
if exitTest():break
三、對比shell的while語句
while 命令
do
命令1
命令2
done
在系統管理時經常使用與逐行讀取一個文件並處理。
while read line
do
echo $line
done < /etc/rc.conf
shell中還有一個相似while的循環until
until 條件
do
命令1
命令2
done
EG:
IS_ROOT=`who |grep root`
until [ "$IS_ROOT" ]
do
echo 'root online'
sleep 2
done
2、 break continue pass和循環的else
break
跳出最近所在的循環(跳出整個循環語句)
continue
跳到最近所在循環的開頭處(來到循環的首行,跳過本次循環)
pass
什麼事也不作,只是空佔位語句
循環else塊
只有當循環正常離開時纔會執行(也就是沒有碰到break語句)
一、通常循環格式
加入break和continue語句後,while循環的通常格式以下:
while <test>:
<statements1>
if <test2>:break
if <test3>:continue
if <test4>:pass
else:
<statements2>
break和continue能夠出如今while(或for)循環主體的任何地方,但一般會進一步嵌套在if語句中,根據某些條件來採起對應的操做。
二、列子
pass
>>> while 1:pass
...
pass可用於空類,有時有指的是"之後會填上」,只是暫時用於填充函數主體而已:
>>> def func1():
... pass
continue
continue語句會當即跳到循環的頂端,開始下一次循環。
>>> while x:
... x=x-1
... if x%2!=0:continue
... print x,
...
8 6 4 2 0
這個例子中,若是是奇數就返回循環頂部,不會打印.是偶數就打印。
這個下面這個結果同樣
>>> while x:
... x=x-1
... if x%2==0:
... print x,
...
8 6 4 2 0
注意這兩個例子的print位置,第一個print是屬於while塊的,測試不經過下執行,測試經過就回到循環頂端,第二個是屬於if塊的,只有測試經過纔打印
>>> while x:
... x=x-1
... if x%2==0:
... print x,
...break
break語句會馬上離開循環。碰到break,位於其後的循環代碼都不會執行。
while 1:
name=raw_input("Enter name:")
if name=='stop':break
age=raw_input("Enter age:")
print 'Hello',name,'=>',int(age)**2
當age不輸入任何值時會報錯。可使用try解決
while 1:
name=raw_input("Enter name:")
if name=='stop':break
age=raw_input("Enter age:")
try:
print 'Hello',name,'=>',int(age)**2
except:
print 'Please input age!'
else 只有當循環正常離開時纔會執行(也就是沒有碰到break語句【break的條件不知足】)
>>> while x:
... x=x-1
... print x
... else:
... print "over"
...
9
8
7
6
5
4
3
2
1
0
over
>>> x=10
>>> while x:
... x=x-1
... if x==5:break
... print x
... else:
... print "over"
...
9
8
7
6
3、for循環
for循環在Python中是一個通用的序列迭代器:能夠遍歷任何有序的序列對象內的元素。for語句可用於字符串,列表,元組,其餘內置可迭代對象以及以後咱們可以經過類所建立的新對象。
一、通常格式
Python for循環的首行定義了一個賦值目標(或【一些目標】),以及你想遍歷的對象,首行後面是你想重複的語句塊(通常都有縮進)
for <target> in <object>:
<statements>
else:
<statements>
當ptyhon運行for循環時,會逐個將序列對象中的元素賦值給目標,而後爲每一個元素執行循環主體。循環主體通常使用賦值的目標來引用序列中當前的元素,就好像那事遍歷序列的遊標。
for首行中用做賦值目標的變量名一般是for語句所在做用於的變量(多是新的)。這個變量名沒有什麼特別的,甚至能夠在循環主體中修改。可是當控制權再次回到循環頂端時,就會自動被設成序列的下一個元素。循環以後,這個變量通常都仍是引用了最近所用過的元素,也就是序列中最後的元素,除非經過一個break語句退出了循環。
for語句也支持一個選用的else塊,它的工做就像在while循環中同樣:若是循環離開時沒有碰到break語句,就會執行(也就是序列全部元素都被訪問過了)
break和continue語句也可用在for循環中,就像while循環那樣。for循環完整的格式以下:
for <target> in <object>:
<statements>
if <test>:break
if <test>:conitnue
else:
<statements>
對比shell的for循環
for 變量名 in 列表
do
命令1
命令1
done
for i in 1 2 3
do
echo $i
don
for i in `ls -1 /root`
do
echo $i
done
二、例子
1)基本應用
>>> x=[1,2,3,4,5]
>>> for i in x:
... print i
...
1
2
3
4
5
>>> for i in x:
... if i==3:break
... print i
...
1
2
>>> for i in x:
... print i
... if i==3:break
...
1
2
3
注意if語句的位置
> D={'name':['diege','lily','kelly'],'class':2012,'number':48}
>>> for i in D:
... print i,'=>',D[i]
...
number => 48
name => ['diege', 'lily', 'kelly']
class => 2012
多層
>>> for i in D:
... if type(D[i])==list:
... for l in D[i]:
... print l
... else:
... print D[i]
...
48
diege
lily
kelly
2012
for元組賦值
首行定義了一個賦值【一些目標】
>>> T=[(1,2),(3,4),(5,6)]
>>> for (a,b) in T:
... print a,b
...
1 2
3 4
5 6
for循環嵌套
遍歷一個字典(或列表)包括字典,列表,元組的的語句
D={'game':'sjgame','version':[1.0,1.1,1.2,1.3],'useid':(1000,1001,1002,1003,1004),'character':{'WS':'wushi','FS':'fashi','MS':'moshi
'},'CP':'ice'}
for i in D:
if type(D[i])==list:
for l in D[i]:
print l
elif type(D[i])==tuple:
for t in D[i]:
print t
elif type(D[i])==dict:
for d in D[i]:
print d
else:
print D[i]
代替break的
>>> items=['diege',999,(3,7),1.3]
>>> tests=[(3,7),3.14]
>>> for key in tests:
... for item in items:
... if key==item:
... print key,'was found'
... break
... else:
... print key,'not found!'
...
(3, 7) was found
3.14 not found
有點相似查找的功能。
收集兩個序列中相同元素
>>> seq1='diege'
>>> seq2='decgl'
>>> res=[]
>>> for x in seq1:
... if x in seq2:
... res.append(x)
...
>>>
>>> res
['d', 'e', 'g', 'e']
準確的說是顯示seq1和seq2都用的在seq1一次順序。
三、爲何要在乎「文件掃描」
循環讀取文件:while在文件結尾時使用break
>>> fl=open('/etc/rc.conf')
>>> while True:
... char=fl.read(1)
... if not char:break
... print char,
MS for循環打印出來的字體正常點,呵呵。
>>> for char in open('/etc/rc.conf'):for char in open('/etc/rc.conf').read():的縮寫
... print char
...
使用while按行處理
>>> fl=open('/etc/rc.conf')
>>> while True:
... line=fl.readline()
... if not line:break
... print line,
...
按行讀取文件文件時,for循環是最容易編寫及執行最快的選擇
>>> for line in open('/etc/rc.conf'):#默認read()
... print line
...
>>> for line in open('/etc/rc.conf').readlines():
... print line
...
readlines會一次把文件載入到行字符串的列表
>>> for line in open('/etc/rc.conf').xreadlines():
... print line
...
xreadlines則是按需求加載文字列,從而避免大型文件致使內存溢出。
每一個步驟所讀取的數據越多,程序會員越快。
4、迭代器:初探
for循環能夠用在任何【可迭代的對象】。這些迭代工具包括了for循環,列表解析,in成員關係測試,以及map內置函數等。
可迭代對象:若是對象是實際保存的序列,或者能夠在迭代工具環境中(如for循環)一次產生一個對象的結果,就被看做是可迭代。
總之,可迭代對象包括實際序列和按照需求而計算的虛擬序列。
一、文件迭代器
文件對象有個方法名爲readline,能夠一次從一個文件中讀取一行文本,每次調用readline方法時,就會前進到下一列,到文件末尾時,就會返回空字符串,能夠經過它來檢查從而跳出循環。文件對象有另一個方法next,差很少用有相同的效果。
>>> fl=open('/etc/rc.conf')
>>> fl.next()
'#apache22_enable="YES"\n'
>>> fl.next()
'# -- sysinstall generated deltas -- # Tue Feb 14 10:08:27 2012\n'
二者的區別在於,達到文件末尾時,next是引起內置的StopIteration異常,而不是返回空字符串。
這個接口就是python所謂的迭代協議:有next方法的對象會前進到下一個結果,而在一些列結果的末尾時,則會引起StopIteration.
在Python中,任何這類對象都認爲是可迭代的。任何這類對象也能以for循環或其餘迭代工具遍歷,由於全部迭代工具內部工做起來都是在每次迭代中調用next,而且捕捉StopIteration異常來肯定什麼時候離開。
逐行讀取文本的最佳方式就是根本不要去讀取,其替代的方法就是,讓for循環在每輪自動調用next從而前進到下一行。
>>> for line in open('/etc/rc.conf'):
... print line.upper(),
逐行讀取文件並轉換爲大寫,注意沒有能夠從文件中讀取內容。
這首讀取文本文件的最佳方式,最簡單,運行最快,內存使用狀況最好。
>>> for line in open('/etc/rc.conf').readlines:
這種方式一次把文件都加載到內存。
二、其餘內置類型迭代器
>>> D={'a':1,'b':2,'c':3}
>>> for key in D.keys():
... print key,D[key]
...
a 1
c 3
b 2
新版無需使用keys方法
>>> for key in D:
... print key,D[key]
...
a 1
c 3
b 2
三、其餘迭代環境
列表解析,in成員關係,map內置函數以及其餘內置工具(如sorted,sum)
>>> [line.upper() for line in open('/etc/rc.conf')]
>>> upper=[line.upper() for line in open('/etc/rc.conf')]
>>> map(str.upper,open('/etc/rc.conf'))
map對迭代對象中每個元素都應用一個函數調用,相似於列表解析,有侷限性,因須要函數,而不是任意表達式。
>>> sorted(open('/etc/rc.conf')) #這個工具排序了,較新的內置函數,採用了迭代協議。應用於任何可迭代的對象上。
>>> sum([3,5,6,9]) #sum調用會計算任何可迭代對象內全部數字的和
23
而若是可迭代對象中的任何元素或者所有元素爲True,內置函數就會返回True:all所有元素爲True才返回True,有一個元素不爲
True,都會返回flase
>>> any(['diege','','ni'])
True
>>> any(['diege','',''])
True
>>> all(['diege','','ni'])
False
>>> all(['diege','a','ni'])
True
其餘工具:list和tuple內置函數(從可迭代對象建立新的對象),字符串join方法(在可迭代對象內字符串之間放入子字符串),以及序列賦值語句等。
>>> list(open('/etc/rc.conf'))
>>> tuple(open('/etc/rc.conf'))
>>> '&&'.join(open('/etc/rc.conf'))
>>> a,d,c,d=open('/etc/rc.conf')
四、用戶定義的迭代器
yield語句能夠把用戶定義的函數變成可迭代的對象。若是的列表解析也能夠經過生成器表達式支持次協議,而用戶定義的類
也能經過__iter__或__getitem__運算符重載方法而變成迭代對象。用戶定義的迭代器能夠在這裏的任何迭代環境中使用任意對象和運算。
5、編寫循環的技巧
遍歷序列時,首選for循環,for循環包括多數計數器式的循環,for比while容易寫,執行時也比較快。
Python提供了兩個內置函數,在for循環內定製迭代:
* 內置range函數返回連續整數列表,可做爲for中的索引。
>>> range(5)
[0, 1, 2, 3, 4]
>>> range(5,10)
[5, 6, 7, 8, 9]
>>> range(5,10,2)
[5, 7, 9]
*內置 zip函數返回並行的元素元祖的列表,可用於在for中遍歷數個序列
一、循環計算器:while和range
>>> range(5),range(2,5),range(3,10,2)
([0, 1, 2, 3, 4], [2, 3, 4], [3, 5, 7, 9])
步進爲負時候爲遞減,默認遞增
>>> range(5,-5,-1)
[5, 4, 3, 2, 1, 0, -1, -2, -3, -4]
range最經常使用於在for循環中,提供一種簡單的方法,重複特定次數的動做。
>>> for i in range(3):
... print i,'pythons'
...
0 pythons
1 pythons
2 pythons
>>> for i in range(0,10,2):
... print i
...
0
2
4
6
8
若是真的要明確地掌控索引邏輯,能夠用while循環來實現。
>>> X='diege'
>>> i=0
>>> while i<len(X):
... print X[i];i+=1
...
d
i
e
g
e
也可使用for進行手動索引,也就是用range產生用於迭代的索引的列表
>>> range(len(X))
[0, 1, 2, 3, 4]
>>> for i in range(len(X)):print X[i],
...
d i e g e
二、非完備遍歷:range
儘可能使用簡單的for循環,不要用while,而且不要在for循環中使用range調用,只將其視爲最後的選擇,更簡單的辦法老是更好。
>>> for i in X:
... print i
...
d
i
e
g
e
使用range能夠作更特殊的遍歷種類。
>>> S='rhrhrfxvlwsocv'
>>> for i in range(0,len(S),2):print S[i]
...
r
r
r
x
l
s
c
更好的辦法
>>> for x in S[::2]:print x
...
r
r
r
x
l
s
c
三、修改列表:range
可使用range和for的組合的常見場合就是在循環中遍歷列表時並對其進行修改。如某些緣由某種理由要爲列表中每一個元素都加1.
>>> L=[1,2,3,4,5]
>>> L
[1, 2, 3, 4, 5]
>>> for i in range(len(L)):
... L[i]+=1
...
>>> L
[2, 3, 4, 5, 6]
四、並行遍歷:zip 和map
>>> L1=[1,2,3,4]
>>> L2=[5,6,7,8]
>>> zip(L1,L2)
[(1, 5), (2, 6), (3, 7), (4, 8)]
>>> for (x,y) in zip(L1,L2):
... print x,y,'--',x+y
...
1 5 -- 6
2 6 -- 8
3 7 -- 10
4 8 -- 12
zip從兩列或者多列中提取出來元素配對。
>>> T1,T2,T3=(1,2,3),(4,5,6),(7,8,9)
>>> zip(T1,T2,T3)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
當參數長度不一樣時,zip會以最短序列的長度爲準來截斷所獲得的元組:
>>> S1='ABC'
>>> S2='xyz123'
>>> zip(S1,S2)
[('A', 'x'), ('B', 'y'), ('C', 'z')]
內置map函數,用相似的方式把序列的元素配對起來,可是若是參數長度,不一樣則會爲較短的序列用None補齊。
>>> map(None,S1,S2)
[('A', 'x'), ('B', 'y'), ('C', 'z'), (None, '1'), (None, '2'), (None, '3')]
使用zip構造字典
>>> keys=['name','age','class']
>>> vals=['diege',18,2012]
>>> zip(keys,vals)
[('name', 'diege'), ('age', 18), ('class', 2012)]
前面學過dict()函數,能夠將k:v組成元組按列表的形式傳送給disc()產生字典。
而zip能夠摻產生這種格式的列表。故可使用
dict(zip(keys,vals)) 構造字典
>>> dict(zip(keys,vals))
{'age': 18, 'name': 'diege', 'class': 2012}
>>> D5=dict(zip(keys,vals))
五、產生偏移和元素:enumerate
enumerate內置函數,同時產生偏移和元素
>>> S='diege'
>>> for (offset,item) in enumerate(S):
... print item,offset
...
d 0
i 1
e 2
g 3
e 4
這個方法有個next方法,每次遍歷列表時,會返回一個(index,value)的元組,而咱們能在for中經過元組賦值運算將其分解。
>>> E=enumerate(S)
>>> E.next()
(0, 'd')
>>> E.next()
(1, 'i')
>>> E.next()
(2, 'e')
>>> E.next()
(3, 'g')
>>> E.next()
(4, 'e')
>>> E.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
6、列表解析:
>>> L=[1,2,3,4,5]
>>> for i in range(len(L)):
... L[I]+=10
... L
>>> L
[1, 2, 3, 4, 5]
這樣解析方式已通過時,這裏用單個表達式取代循環,來產生所須要的結果列表
>>> L=[1,2,3,4,5]
>>> L=[x+10 for x in L]
>>> L
[11, 12, 13, 14, 15]
一、列表解析基礎
列表解析是寫在方括號中的,由於它畢竟是一種建立新的列表的方式。它是咱們編寫的任何表達式開始,而該表達式中使用了一個咱們所編寫循環的變量(x+10)。後面所接的就是for循環的首行,指出循環變量的名稱以及可迭代的對象(for x in L)
[【表達式】 for x in L【for循環行首】]
技術角度,列表解析毫不是必需要求。由於可使用for循環,在遍歷的過程當中把表達式結果加在列表上。
>>> res=[]
>>> L
[11, 12, 13, 14, 15]
>>> for x in L:
... res.append(x+10)
...
>>> L
[11, 12, 13, 14, 15]
不過列表解析寫起來更簡明,這種建立結果列表的編碼模式在Python中是很常見的工做。並且運行更快,是以C語言的速度執行。
二、對文件使用列表解析
>>> f=open('/etc/rc.conf')
>>> lines=f.readlines()
>>> lines
['#apache22_enable="YES"\n', '# -- sysinstall generated deltas -- # Tue Feb 14 10:08:27 2012\n', 'ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"\n', '#ifconfig_em0="DHCP"\n', '# -- sysinstall generated deltas -- # Tue Feb 14 10:09:24 2012\n', 'ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"\n', '#hostname="ofreebsd.corp.icee.cn"\n', 'hostname="ofreebsd.skylog.cn"\n', '# -- sysinstall generated deltas -- # Tue Feb 14 10:12:04 2012\n', 'sshd_enable="YES"\n', '#mysql_enable="YES"\n']
列表中包含的有換行符,若是想去掉換行符怎麼辦呢?
想到字符串的rstrip方法,可是怎麼應用呢?也可使用(line[:-1]也能夠
>>> lines=[line.rstrip() for line in lines]
>>> lines
['#apache22_enable="YES"', '# -- sysinstall generated deltas -- # Tue Feb 14 10:08:27 2012', 'ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"', '#ifconfig_em0="DHCP"', '# -- sysinstall generated deltas -- # Tue Feb 14 10:09:24 2012', 'ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"', '#hostname="ofreebsd.corp.icee.cn"', 'hostname="ofreebsd.skylog.cn"', '# -- sysinstall generated deltas -- # Tue Feb 14 10:12:04 2012', 'sshd_enable="YES"', '#mysql_enable="YES"']
若是是打開文件讀取文件,徹底能夠不用事先打開,能夠在表達式內開啓它。
>>> lines=[line.rstrip() for line in open('/etc/rc.conf')]
三、擴展列表解析語句
列表解析在實際使用中能夠更高級。表達式中嵌套的for循環能夠結合一個if分句來過濾測試不爲真的結果元素,這但是一項有用的擴展功能。
重複上一個例子,但咱們只需開頭不爲#的文字行。
>>> lines=[line.rstrip() for line in open('/etc/rc.conf') if line[0]!='#']
>>> lines
['ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"', 'ifconfig_em1="inet 192.168.1.200 netmask 255.255.255.0"', 'hostname="ofreebsd.skylog.cn"', 'sshd_enable="YES"']
更復雜的狀況,列表解析也能夠含有嵌套循環,寫成一系列的for分句。實際上,其完整的語句可接納任意數目的for分句,而每一個分區均可以結合一個可選的if分句
>>> [x+y for x in 'abc' for y in 'lmn']
['al', 'am', 'an', 'bl', 'bm', 'bn', 'cl', 'cm', 'cn']
對一個字符串中的每一個x,以及另外一個字符串中的每一個y,建立x+y合併的列表。收集兩個字符串字符的排列組合python