函數是一種功能上的抽象,比如當我們寫一段程式,這個程式多次用到了發送郵件的功能(比如說:每天三點固定發送郵件,每當伺服器負載較重發送郵件提醒……),那麼我們就可以將發送郵件這個功能抽象出來,單獨對其定義一個函數進行實現。這樣在需要引用發送郵件功能的時候,我們就不需要重覆複製代碼,直接調用函數就可以了 ...
函數是一種功能上的抽象,比如當我們寫一段程式,這個程式多次用到了發送郵件的功能(比如說:每天三點固定發送郵件,每當伺服器負載較重發送郵件提醒……),那麼我們就可以將發送郵件這個功能抽象出來,單獨對其定義一個函數進行實現。這樣在需要引用發送郵件功能的時候,我們就不需要重覆複製代碼,直接調用函數就可以了。另外的過程易讀性強,方便修改也是函數的兩大優點。
函數的分類:
函數大體上可以分為兩類--內置函數和自定義函數
內置函數:
簡單的介紹一下幾個函數的功能:
abs():取絕對值 divmod():除整取餘 input():輸入 max():返回其中的最大值 id():返回該對象的標識符
然後介紹一些可能會用到的函數:
#對所有可迭代的對象進行判斷,若有一個為空,則返回False >>> all('123') True >>> all([1,2,3]) True #當有一個元素為空時 >>> all(['',2]) False #但是,輸入一個空的列表則不會返回False >>> all([]) Trueall()所有為真則為真,else:為假
#當有一個為非空,則返回True >>> any('123') True >>> any([0, 1]) True >>> any([0, '']) Falseany() 有一個為真則為真,所有為假則為假
# for i,j in enumerate([1,2,3]): print(i,j) 0 1 1 2 2 3 #字典也可以進行枚舉,只是順序可變 for i,j in enumerate({'a':2,'b':3}): print(i,j) 0 b 1 aenumerate()遍歷序列中的元素以及它們的下標
>>> eval('2+3') 5 #將字元串2+3轉換為整數計算表達式,並返回計算結果 >>> eval('sdfdfsd') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> NameError: name 'sdfdfsd' is not definedeval()將字元串str當成有效Python表達式來求值,並返回計算結果
>>> round(2.3)
2
round()四捨五入
>>> sum([1,2,3]) 6 >>> max(1,2,3) 3 >>> min(1,2,3) 1sum() max() min() 求和,取最大值,取最小值
#chr() 將ascii碼中的數字(0--255)轉換為對應的字元 >>> chr(65) 'A' #ord()將字元轉換為對應的ascii碼 >>> ord('t') 116chr() ord() ascii碼與字元的相互轉換
>>> pow(2,2)
4
pow() 冪
open('test','r+',encoding='utf-8')open(‘路徑’,'模式',encoding=……可選) 打開文件
x = [1, 2, 3] y = [4, 5, 6] z = [7, 8, 9] u = zip(x, y, z) print u #結果是: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] #當兩個序列元素個數不一致時,zip會產生元素個數最小的那個序列的元素個數的值 x = [1, 2, 3] y = [4, 5, 6,7] u=zip(x,y) print(u) #結果是: [(1,4),(2,5),(3,6)]zip()接受任意多個(包括0個和1個)序列作為參數,返回一個tuple列表
>>> sorted([1,4,2,5,3])
[1, 2, 3, 4, 5]
sorted()排序
自定義函數:
#def是關鍵字 用來定義函數 def obj(): pass #什麼也不做 obj()
上例就是一個最簡單的自定義函數的格式,它是一個空函數。
函數的返回值:
當我們運行完一個函數,這個函數有許多可能的結果,比如說報錯缺少文件,報錯缺少庫,運行成功,報錯密碼不對……我們想知道具體的結果,這時就可以用到返回值,比如1表示運行成功,404表示not found……
return可以返回值,還表示函數的終止!
def obj(): n1=2 if n1==3: return 0 else: return 1 ret=obj() print(ret)
1 #結果
當然也可以返回多個值:
def obj(): n1=2 if n1==3: return 0,1 else: return 1,2 ret=obj() print(ret) (1,2) #結果
由此可見,返回多個值時返回的是一個tuple。
參數:
在上面的例子中函數都是無參數的,實際應用中,很多函數都是有參數的,並且參數可以有多個,甚至允許有動態參數。
多個參數:
def show(a,b,c=2): print(a,b,c) show(1,3) 1,3,2 #結果 show(b=3,a=2) 1,3,2 #結果
在上面的例子中不僅有多個參數,還有預設參數
預設參數:
預設參數代表如果沒有賦值,就按照預設值返回,若賦值,在按照所賦予的值返回。
並且必選參數在前,預設參數在後,否則Python的解釋器會報錯。
預設參數存在一個問題,我無恥的參(fu)考(zhi)了廖雪峰大神的python教程:
先定義一個函數,傳入一個list,添加一個END
再返回:
def add_end(L=[]): L.append('END') return L
當你正常調用時,結果似乎不錯:
>>> add_end([1, 2, 3]) [1, 2, 3, 'END'] >>> add_end(['x', 'y', 'z']) ['x', 'y', 'z', 'END']
當你使用預設參數調用時,一開始結果也是對的:
>>> add_end() ['END']
但是,再次調用add_end()
時,結果就不對了:
>>> add_end() ['END', 'END'] >>> add_end() ['END', 'END', 'END']
很多初學者很疑惑,預設參數是[]
,但是函數似乎每次都“記住了”上次添加了'END'
後的list。
原因解釋如下:
Python函數在定義的時候,預設參數L
的值就被計算出來了,即[]
,因為預設參數L
也是一個變數,它指向對象[]
,每次調用該函數,如果改變了L
的內容,則下次調用時,預設參數的內容就變了,不再是函數定義時的[]
了。
所以,定義預設參數要牢記一點:預設參數必須指向不變對象!
要修改上面的例子,我們可以用None
這個不變對象來實現:
def add_end(L=None): if L is None: L = [] L.append('END') return L
現在,無論調用多少次,都不會有問題:
>>> add_end() ['END'] >>> add_end() ['END']
為什麼要設計str
、None
這樣的不變對象呢?因為不變對象一旦創建,對象內部的數據就不能修改,這樣就減少了由於修改數據導致的錯誤。此外,由於對象不變,多任務環境下同時讀取對象不需要加鎖,同時讀一點問題都沒有。
我們在編寫程式時,如果可以設計一個不變對象,那就儘量設計成不變對象。
另外在賦值時,可以通過指定參數而不用按照順序進行賦值。
動態參數:
所謂動態參數,就是傳入的參數是動態的,即數目不確定。實際上就是將輸入的所有參數存儲為一個元組或者字典。
如果要定義一個tuple的動態參數,只需要在定義參數時在參數前添加一個*。
def show(*a): print(a) show(1,2,3) (1,2,3) #結果
上例就是將所有參數轉換為一個tuple。
如果要定義一個dict的動態參數,只需要在定義參數時在參數前添加兩個*。
def show(**a): print(a) show(n1=1,n2=2) {'n2': 2, 'n1': 1} #結果