1. 程式人生 > >第五章:條件、循環和其它語句

第五章:條件、循環和其它語句

tde pop 空格 fin program 比較 isspace 才有 刪除

5.1 print和import的更多使用方式

5.1.1 使用逗號輸出

print Age,42
print 1,2,3
如果要同時輸出文本和變量值,又不希望使用字符串格式化的話,那麽這個特性就比較有用了
>>> name = Gumby
>>> salutation = Mr.
>>> greeting = Hello
>>> print greeting,salutation,name
Hello Mr. Gumby
>>> print greeting + ,
,salutation,name Hello, Mr. Gumby >>> print greeting,,,salutation,name Hello , Mr. Gumby

5.1.2 把某件事作為另一件事導入

導入模塊的方法:以下四種
import somemodule
from somemodule import somefunction
from somemodule import somefunction1 somefunction2 somefunction3
from somemodule import *
另一種方式,為模塊提供別名
>>> import
math as foobar >>> print foobar.sqrt(9) 3.0
或者為函數提供別名
>>> from math import sqrt as foobar
>>> foobar(4)
2.0

5.2 賦值魔法

就算是不起眼的賦值豫劇也有一些特殊的技巧

5.2.1 序列解包

多個賦值操作同時進行:
>>> x,y,z = 1,2,3
>>> print x,y,z
1 2 3
交換變量:
>>> y=x
>>> print
x,y,z 1 1 3 >>> x,z=z,x >>> print x,y,z 3 1 1
上面的操作過程叫做序列解包或遞歸解包 當函數或者方法返回元組(或者其他序列或可叠代對象)時,這個特性比較有用。假設需要獲取(和刪除)字典中的任意的鍵-值對,可以使用popitem方法,這個方法將鍵值作為元組返回,那麽這個元組就可以直接賦值到兩個變量中。
>>> dd = {name:Anti,Age:42}
>>> key,value = dd.popitem()
>>> key
Age
>>> value
42

5.2.2 鏈式賦值

鏈式賦值是將同一個值賦給多個變量的捷徑。它看起來有些像並行賦值 示例如下:
x = y = somefunction()
#
y = somefunction()
x = y
另一個:
x = somefunction()
y = somefunction()
上面的兩種表達式起到的效果是不一樣的

5.2.3 增量賦值

>>> x = 2
>>> x += 1  #加等
>>> x
3
>>> x *= 6  #乘等
>>> x
18
>>> x -= 2  #減等
>>> x
16
增量賦值讓代碼更加緊湊和簡練易讀

5.3 語句塊

在python中,冒號(:)用來標識語句塊的開始,塊中的每一個語句都是縮進的(縮進量相同)

5.4 條件和條件語句

5.4.1 布爾變量的作用

真值,也叫作布爾值,有Ture和False兩種 False的幾種形式:None,False,0,(空),(),[],{} bool函數用來(和list,str以及tuple一樣)轉換其他值
>>> bool(I think, therefor I am.)
True
>>> bool([])
False
>>> bool({name:Aoto})
True
>>> bool(0)
False

5.4.2 條件執行和if語句

if語句可以用來實現條件執行

5.4.3 else子句

name = raw_input("What‘s your name ? ")
if name.endswith(Gumby):
    print Hello, Mr.Gumby.
else:
    print Hello, stranger.
#輸出如下
Whats your name ? Gumby
Hello, Mr.Gumby.

5.4.4 elif語句

if ...:
    do ...
elif ...:
    do ...
else:
    do ...

5.4.5 嵌套代碼塊

if語句中嵌套使用if語句

5.4.6 更復雜的條件

1.比較運算符

常見的如下: x == y:x等於y x < y:x小於y x > y:x大於y x >= y:x大於等於y x <= y:x小於等於y x != y:x不等於y x is y:x和y是同一對象 x is not y:x和y不是同一對象 x in y:x是y的容器(如:序列)的成員 x not in y:x不是y的容器(如:序列)的成員 只有當x和y是相同或相近類型的對象時,比較才有意義 在python3中,比較不兼容的兩個對象已經不再可行

2.相等運算符:==

單個相等運算符是賦值運算符,是用來改變值得,而不是用來比較

3.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運算符是判定同一性而不是相等性的。x和y都被綁定在同一個列表上,而變量z被綁定在另一具有相同數值和順序的列表上。它們的值可能相同,但卻不是同一個對象 總結:使用(==)運算符來判定兩個對象是否相等,使用is判定兩者是否相同

4.in:成員資格運算符

5.字符串和序列比較

6.布爾運算符

number = input(Enter a number between 1 and 10 : )
if number <= 10 and number > 1:
    print Great!
else:
    print Wrong!

#輸出如下
Enter a number between 1 and 10 : 8
Great!
and運算符在兩者都為真時返回真,否則返回假,與and類似的還有or(或)和not(否) 用處:
name = raw_input(Please input your name: ) or <Unknow>
print name


#輸出如下:
Please input your name: 
<Unknow>


#輸出如下:
Please input your name: Aoto
Aoto
三元運算符:
a if b else c
如果b為真,返回a,否則返回c
x=2 if 10>=2 else 4
print x


result = gt if 1 >3 else lt
print result

5.4.7 斷言:assert

if not condition:
    crash program
什麽時候需要這樣的代碼? 就是因為與其讓程序與其在晚些時候崩潰,不如在錯誤條件出現時直接讓他崩潰。一般來說,你可以要求某些條件必須為真。語句中使用的關鍵字是assert
>>> age = 10
>>> assert 0 < age < 100
>>> age = -1
>>> assert 0 < age < 100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
如果需要確保程序中的某一個條件一定為真才能讓程序正常工作的話,assert語句就有用了,他可以在程序中植入檢查點 條件之後可以添加字符串,用來解釋斷言
>>> age = -1
>>> assert 0 < age < 100, The age must be reallistic.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: The age must be reallistic.

5.5 循環

5.5.1 while循環

name = ‘‘
while not name or name.isspace():
    name = raw_input(Please enter your name: )
print Hello,%s! % name
#輸出如下:
Please enter your name:    
Please enter your name:  #輸入空格是無效的,要求重新輸入
Please enter your name: dodo
Hello,dodo!

5.5.2 for循環

kl = []
for i in range(1,10,2):
    kl.append(i)
print kl


#輸出如下
[1, 3, 5, 7, 9]
提示:如果能使用for循環,就盡量不要使用while循環 range與xrange: xrange函數的循環類似於range函數,區別愛與range函數一次性創建整個序列,而xrange一次只創建一個數。當需要叠代一個巨大的序列時xrange會更高效,不過一般情況下還是用range即可。

5.5.3 循環遍歷字典元素

>>> d = {name:ToTo,Age:23,Address:BeiJing}
>>> for key in d:
...     print key,corresponds to,d[key]
... 
Age corresponds to 23
name corresponds to ToTo
Address corresponds to BeiJing

>>> for k,v in d.items():
...     print k,corresponds to,v
... 
Age corresponds to 23
name corresponds to ToTo
Address corresponds to BeiJing

5.5.4 一些叠代工具

1.並行叠代

names = [Anne,Beth,George,Damon]
ages  = [12,23,78,67]
for name,age in zip(names,ages):
    print name,is,age,years old.

#輸出如下
Anne is 12 years old.
Beth is 23 years old.
George is 78 years old.
Damon is 67 years old.
程序可以同時叠代兩個序列 而內建的zip命令就可以用來進行並行叠代,可以把兩個序列壓縮在一起,然後返回一個元組的列表
name = [Anne,Beth,George,Damon]
age  = [12,23,78,67]
for i in range(len(name)):
    print name[i],is,age[i],years old.

#輸出如下
Anne is 12 years old.
Beth is 23 years old.
George is 78 years old.
Damon is 67 years old.
zip函數也可以作用於人一多的序列。關於他的很重要的一點是zip可以處理不等長的序列,當最短的序列“用完”的時候就會停止
zip(range(5),xrange(1000))
輸出:[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
在上面的代碼中,不推薦用range替換掉xrange,盡管只需要前5個數字,但是range會計算出所有的數字,這需要花費較長的時間

2.按索引叠代

有時候想要叠代訪問序列中的對象,同時還要獲取當前對象的索引 方法一:
for string in strings:
    if xxx in string:
        index = strings.index(string)
        strings[index] = [censored]
方法二:
index = 0
for string in strings:
    if xxx in string:
        strings[index] = [censored]
    index += 1
方法三: 使用內建的enumerate函數
for index,string in enumerate(strings):
    if xxx in string:
        string[index] = [censored]
上面的用法還是沒搞懂怎麽更好的使用

3.翻轉和排序叠代:reversed和sorted

它們作用於任何序列或可叠代對象上,不是原地修改對象,而是返回翻轉或排序後的版本
>>> sorted([4,3,5,2,3,6,9,0])
[0, 2, 3, 3, 4, 5, 6, 9]
>>> 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

5.5.5 跳出循環

1.break

from math import sqrt
for n in range(99,0,-1):
    root = sqrt(n)
    if root == int(root):
        print root,n
        break

#結果如下,求出0-100範圍內最大的平方數
9.0 81

2.continue

它最基本的意思是:跳過剩余的循環體,但是不結束循環。當循環體很大且很復雜的時候比較有效。 它會將當前的叠代結束,“跳”到下一輪循環開始 例1:
for x in seq:
    if condition1:continue
    if condition2:continue
    if condition3:continue
    
    do_something()
    do_something_else()
    do_another_thing()
    etc()
例2:
for x in seq:
    if not(condition1 or condition1 or condition1):
        do_something()
        do_something_else()
        do_another_thing()
        etc()

3.while True/break習語:

while True:
    word = raw_input(Please enter a word: )
    if not word: break
    #處理word
    print The word was  + word

4.循環中的else語句

from math import sqrt
for n in range(99,0,-1):
    root = sqrt(n)
    if root == int(root):
        print root,n
        break
else:
    print "Don‘t find it."

5.6 列表推導式:輕量級循環

例:
>>> [x*x for x in range(5)]
[0, 1, 4, 9, 16]
>>> [x*x for x in range(10) if x%3 == 0]
[0, 9, 36, 81]
>>> [(x,y) for x in range(3) for y in range(3) if y<=x]
[(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)]
>>> [(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)]
問題:篩選出名字首字母相同的男孩和女孩 方法一:
girls = [alice,bernice,clarice]
boys  = [chris,arnord,bob]
print [boy +  +  + girl for boy in boys for girl in girls if boy[0]==girl[0]]
#結果如下
[chris + clarice, arnord + alice, bob + bernice]
方法二:
girls = [alice,bernice,clarice,bibl]
boys  = [chris,arnord,bob]
letterGirls = {}
for girl in girls:
    letterGirls.setdefault(girl[0],[]).append(girl)
print letterGirls
print [Boy +  +  + Girl for Boy in boys for Girl in letterGirls[Boy[0]]]

#結果如下
{a: [alice], c: [clarice], b: [bernice, bibl]}
[chris + clarice, arnord + alice, bob + bernice, bob + bibl]
這個程序建造了一個叫做letterGirl的字典,其中的每一項都把單字母作為鍵,以女孩名字組成的列表作為值。在字典建立後,列表推導式循環整個男孩集合,並且查找那些和當前男孩名字首字母相同的女孩集合。這樣列表推導式就不用嘗試手遊的男孩、女孩的組合,檢查首字母是否匹配。

5.7 三人行:pass、del、exec

5.7.1 什麽都沒發生:pass

有的時候,程序什麽事情都不用做 那麽什麽時候會用到pass? 他可以在代碼中做占位符使用,比如程序要一個if語句,然後測試,但是缺少其中一個語句塊的代碼,就會用到:
if name == Raplh Auldus Melish:
    print "Welcome!"
elif name == Enid:  
#在elif這個代碼塊中,必須要有一個執行語句,否則空代碼塊在Python中是非法的,解決方法就是加一個pass
    #還沒完
    pass
elif name == Bill Gates:
    print "Access Denied!"

5.7.2 使用del刪除

一般來說,python會刪除那些不再使用的對象,進行內存的垃圾回收 del語句不僅會移除一個對象的引用,也會移除那個名字本身
>>> x = 1
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name x is not defined
看起來簡單,理解起來難 例:x和y都指向同一個列表
>>> x = ["Hello",World]
>>> y = x
>>> y[1] = "python"
>>> x
[Hello, python]
會有人認為刪除x之後,y就會隨之消失了,但是並非如此
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name x is not defined
>>> y
[Hello, python]
為什麽?x和y都指向同一個列表。但是刪除x並不會影響y。原因就是刪除的只是名稱,不是列表本身(值)。事實上,在python中是沒有辦法刪除值得,也不需要過多考慮刪除值的問題,因為某個值不再使用的時候,python解釋器會負責內存的回收。

5.7.3 使用exec和eval執行和求值字符串

1.exec

執行一個字符串的語句
>>> exec "print ‘Hello,world!‘"
Hello,world!
使用簡單的exec絕不是好事。很多錢款下可以給它提供命名空間--可以放置變量的地方。你想這樣做,從而使代碼不會幹擾命名空間(也就是你的變量),比如,下面的代碼中使用了名稱sqrt:
>>> from math import sqrt
>>> exec "sqrt = 1"
>>> sqrt(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int object is not callable
為什麽這樣做?exec語句最有用的地方在於可以動態的創建代碼字符串。如果字符串是從其他地方獲得的---很可能是用戶---那麽幾乎不能確定其中到底有什麽代碼。所以為了安全起見,可以增加一個支點,起到命名空間的作用。 命名空間的概念,或稱為作用域(scope)
>>> from math import sqrt
>>> scope = {}
>>> exec sqrt = 1 in scope
>>> sqrt(4)
2.0
>>> scope[sqrt]
1
可以看到,潛在的破壞性代碼並不會覆蓋sqrt函數,原來的函數能正常工作,而通過exec賦值的變量sqrt只在它的作用域內有效。

2.eval

是類似於exec的內建函數 跟exec一樣,eval也可以使用命名空間。盡管表達式幾乎不像語句那樣為變量重新賦值。(實際上,可以給eval語句提供兩個命名空間,一個是全局的,一個是局部的。全局的必須是字典,局部的可以是任何形式的映射。)

5.8 小結

1.打印:print 2.導入:import 3.賦值:序列解包、鏈式賦值 4.塊:通過縮排使語句成組的一種方法 5.條件 6.斷言 7.循環 8.列表推導式 9.pass、del、eval、exec

第五章:條件、循環和其它語句