Python入門基礎之函數、切片
Python之函數
Python不但能非常靈活地定義函數,而且本身內置了很多有用的函數,可以直接調用。
Python之調用函數
Python內置了很多有用的函數,我們可以直接調用。
要調用一個函數,需要知道函數的名稱和參數,比如求絕對值的函數 abs,它接收一個參數。
可以直接從Python的官方網站查看文檔:
http://docs.python.org/2/library/functions.html#abs
也可以在交互式命令行通過 help(abs) 查看abs函數的幫助信息。
調用 abs 函數:
>>> abs(100) 100 >>> abs(-20)20 >>> abs(12.34) 12.34
調用函數的時候,如果傳入的參數數量不對,會報TypeError的錯誤,並且Python會明確地告訴你:abs()有且僅有1個參數,但給出了兩個:
>>> abs(1, 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: abs() takes exactly one argument (2 given)
如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報TypeError的錯誤,並且給出錯誤信息:str是錯誤的參數類型:
>>> abs(‘a‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: bad operand type for abs(): ‘str‘
而比較函數 cmp(x, y) 就需要兩個參數,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1:
>>> cmp(1, 2) -1 >>> cmp(2, 1) 1 >>> cmp(3, 3) 0
Python內置的常用函數還包括數據類型轉換函數,比如 int()函數可以把其他數據類型轉換為整數:
>>> int(‘123‘) 123 >>> int(12.34) 12
str()函數把其他類型轉換成 str:
>>> str(123) ‘123‘ >>> str(1.23) ‘1.23‘
sum()函數接受一個list作為參數,並返回list所有元素之和。請計算 1*1 + 2*2 + 3*3 + ... + 100*100。
L = [] x = 1 while x <= 100: L.append(x * x) x = x + 1 print sum(L)
Python之編寫函數
在Python中,定義一個函數要使用 def 語句,依次寫出函數名、括號、括號中的參數和冒號:,然後,在縮進塊中編寫函數體,函數的返回值用 return 語句返回。
我們以自定義一個求絕對值的 my_abs 函數為例:
def my_abs(x): if x >= 0: return x else: return -x
請註意,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,並將結果返回。因此,函數內部通過條件判斷和循環可以實現非常復雜的邏輯。
如果沒有return語句,函數執行完畢後也會返回結果,只是結果為 None。
return None可以簡寫為return。
Python函數之返回多值
數可以返回多個值嗎?答案是肯定的。
比如在遊戲中經常需要從一個點移動到另一個點,給出坐標、位移和角度,就可以計算出新的坐標:
# math包提供了sin()和 cos()函數,我們先用import引用它:
import math def move(x, y, step, angle): nx = x + step * math.cos(angle) ny = y - step * math.sin(angle) return nx, ny
這樣我們就可以同時獲得返回值:
>>> x, y = move(100, 100, 60, math.pi / 6) >>> print x, y 151.961524227 70.0
但其實這只是一種假象,Python函數返回的仍然是單一值:
>>> r = move(100, 100, 60, math.pi / 6) >>> print r (151.96152422706632, 70.0)
用print打印返回結果,原來返回值是一個tuple!
但是,在語法上,返回一個tuple可以省略括號,而多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函數返回多值其實就是返回一個tuple,但寫起來更方便。
Python之遞歸函數
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
舉個例子,我們來計算階乘 n! = 1 * 2 * 3 * ... * n,用函數 fact(n)表示,可以看出:
def fact(n): if n==1: return 1 return n * fact(n - 1)
遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
使用遞歸函數需要註意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。可以試試計算 fact(10000)。
Python之定義默認參數
定義函數的時候,還可以有默認參數。
例如Python自帶的 int() 函數,其實就有兩個參數,我們既可以傳一個參數,又可以傳兩個參數:
>>> int(‘123‘) 123 >>> int(‘123‘, 8) 83
int()函數的第二個參數是轉換進制,如果不傳,默認是十進制 (base=10),如果傳了,就用傳入的參數。
可見,函數的默認參數的作用是簡化調用,你只需要把必須的參數傳進去。但是在需要的時候,又可以傳入額外的參數來覆蓋默認參數值。
我們來定義一個計算 x 的N次方的函數:
def power(x, n): s = 1 while n > 0: n = n - 1 s = s * x return s
假設計算平方的次數最多,我們就可以把 n 的默認值設定為 2:
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s
這樣一來,計算平方就不需要傳入兩個參數了:
>>> power(5)
25
由於函數的參數按從左到右的順序匹配,所以默認參數只能定義在必需參數的後面:
# OK: def fn1(a, b=1, c=2): pass # Error: def fn2(a=1, b): pass
Python之定義可變參數
如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數:
def fn(*args): print args
可變參數的名字前面有個 * 號,我們可以傳入0個、1個或多個參數給可變參數:
>>> fn() () >>> fn(‘a‘) (‘a‘,) >>> fn(‘a‘, ‘b‘) (‘a‘, ‘b‘) >>> fn(‘a‘, ‘b‘, ‘c‘) (‘a‘, ‘b‘, ‘c‘)
可變參數也不是很神秘,Python解釋器會把傳入的一組參數組裝成一個tuple傳遞給可變參數,因此,在函數內部,直接把變量 args 看成一個 tuple 就好了。
定義可變參數的目的也是為了簡化調用。假設我們要計算任意個數的平均值,就可以定義一個可變參數:
def average(*args): sum = 0.0 if len(args) == 0: return sum for x in args: sum = sum + x return sum / len(args)
這樣,在調用的時候,可以這樣寫:
>>> average() 0 >>> average(1, 2) 1.5 >>> average(1, 2, 2, 3, 4) 2.4
對list進行切片
取一個list的部分元素是非常常見的操作。比如,一個list如下:
>>> L = [‘Adam‘, ‘Lisa‘, ‘Bart‘, ‘Paul‘]
取前3個元素,應該怎麽做?
笨辦法:
>>> [L[0], L[1], L[2]] [‘Adam‘, ‘Lisa‘, ‘Bart‘]
之所以是笨辦法是因為擴展一下,取前N個元素就沒轍了。
取前N個元素,也就是索引為0-(N-1)的元素,可以用循環:
>>> r = [] >>> n = 3 >>> for i in range(n): ... r.append(L[i]) ... >>> r [‘Adam‘, ‘Lisa‘, ‘Bart‘]
對這種經常取指定索引範圍的操作,用循環十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡化這種操作。
對應上面的問題,取前3個元素,用一行代碼就可以完成切片:
>>> L[0:3] [‘Adam‘, ‘Lisa‘, ‘Bart‘]
L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素。
如果第一個索引是0,還可以省略:
>>> L[:3] [‘Adam‘, ‘Lisa‘, ‘Bart‘]
也可以從索引1開始,取出2個元素出來:
>>> L[1:3] [‘Lisa‘, ‘Bart‘]
只用一個 : ,表示從頭到尾:
>>> L[:] [‘Adam‘, ‘Lisa‘, ‘Bart‘, ‘Paul‘]
因此,L[:]實際上復制出了一個新list。
切片操作還可以指定第三個參數:
>>> L[::2] [‘Adam‘, ‘Bart‘]
第三個參數表示每N個取一個,上面的 L[::2] 會每兩個元素取出一個來,也就是隔一個取一個。
把list換成tuple,切片操作完全相同,只是切片的結果也變成了tuple。
例子:
range()函數可以創建一個數列:
>>> range(1, 101)
[1, 2, 3, ..., 100]
請利用切片,取出:
1. 前10個數;
2. 3的倍數;
3. 不大於50的5的倍數。
L = range(1, 101) print L[:10] print L[2::3] print L[4:50:5]
倒序切片
對於list,既然Python支持L[-1]取倒數第一個元素,那麽它同樣支持倒數切片,試試:
>>> L = [‘Adam‘, ‘Lisa‘, ‘Bart‘, ‘Paul‘] >>> L[-2:] [‘Bart‘, ‘Paul‘] >>> L[:-2] [‘Adam‘, ‘Lisa‘] >>> L[-3:-1] [‘Lisa‘, ‘Bart‘] >>> L[-4:-1:2] [‘Adam‘, ‘Bart‘]
記住倒數第一個元素的索引是-1。倒序切片包含起始索引,不包含結束索引。
註意:-4要在-1前面;同樣地,-3也得在-1前面。即使是倒序切片,排倒數第一的依舊在後面。
對字符串切片
字符串 ‘xxx‘和 Unicode字符串 u‘xxx‘也可以看成是一種list,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:
>>> ‘ABCDEFG‘[:3] ‘ABC‘ >>> ‘ABCDEFG‘[-3:] ‘EFG‘ >>> ‘ABCDEFG‘[::2] ‘ACEG‘
在很多編程語言中,針對字符串提供了很多各種截取函數,其實目的就是對字符串切片。Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成,非常簡單。
例子:
>>> ‘abc‘.upper() ‘ABC‘
但它會把所有字母都變成大寫。請設計一個函數,它接受一個字符串,然後返回一個僅首字母變成大寫的字符串。
提示:利用切片操作簡化字符串操作。
def firstCharUpper(s): return s[0].upper() + s[1:]
參考慕課網課程:http://www.imooc.com/learn/177
Python入門基礎之函數、切片