今天是Python函數專題,目錄結構:
很多人學習python,不知道從何學起。
很多人學習python,掌握了基本語法過後,不知道在哪裏尋找案例上手。
很多已經做案例的人,卻不知道如何去學習更加高深的知識。
那麼針對這三類人,我給大家提供一個好的學習平臺,免費領取視訊教學,電子書籍,以及課程的原始碼!
QQ羣:101677771
Python 函數專題
基礎部分
1 函陣列成
2 參照傳參
3 預設參數與關鍵字參數
4 可變參數
5 內建函數
進階部分
6 偏函數
7 遞回函數
8 匿名函數
9 高階函數
10 巢狀函數
總結
函數是一個接受輸入、進行特定計算併產生輸出的語句集。
我們把一些經常或反覆 反復被使用的任務放在一起,建立一個函數,而不是爲不同的輸入反覆 反復編寫相同的程式碼。
Python提供了print
、sorted
、max
、map
等內建函數,但我們也可以建立自己的函數,稱爲使用者定義函數。
如下自定義函數:
def foo(nums):
""" 返回偶數序列"""
evens = []
for num in nums:
if num%2==0:
evens.append(num)
return evens
可以看到函數主要組成部分:
函數名:foo
函數形參:nums
:
: 函數體的控制字元,作用類似Java
或C++
的一對{}
縮排:一般爲4個字元
"""
:爲函數新增註 加注釋
return
: 函數返回值
以上函數求出列表nums
中的所有偶數並返回,通過它瞭解Python函數的主要組成部分。
定義好一個函數後,使用:函數名+()+實參,呼叫函數,如下方法:
foo([10,2,5,4])
其中[10,2,5,4]
爲實參,它通過by reference
方式傳給形參nums
,即nums
指向列表頭,而不是重新複製一個列表給nums
.
再看一個參照的例子:
def myFun(x):
x[0] = 20
如下呼叫:
lst = [10, 11, 12, 13, 14, 15]
myFun(lst)
實參lst
和形參x
都指向同一個列表:
因此,對x[0]
修改實際就是對實參lst
的修改,結果如下:
但是,有時在函數內部形參指向改變,因此實參與形參的指向分離,如下例子:
def myFun(x):
x = [20, 30, 40]
x[0] = 0
呼叫:
lst = [10, 11, 12, 13, 14, 15]
myFun(lst)
x
被傳參後初始指向lst
,如下所示:
但是,執行x = [20, 30, 40]
後,物件x
重新指向一個新的列表物件[20,30,40]
:
因此,對於x
內元素的任何修改,都不會同時影響到lst
,因爲指向已經分離。
Python函數的參數,可以有初始預設值,在呼叫時如果不賦值,則取值爲預設值,如下例子:
def foo(length,width,height=1.0):
return length*width*height
呼叫foo
函數,沒有爲height
傳參,所以取爲預設值1.0
:
r = foo(1.2,2.0)
print(r) # 2.4
使用預設值有一點需要區分,有的朋友會與關鍵字參數混淆,因爲它們都是para=value
的結構,但是有一個很明顯的不同:預設值是宣告在函數定義時,關鍵字參數是在函數呼叫時使用的此結構。如下例子:
def foo(length,width,height=1.0): # height是預設參數
return length*width*height
foo(width=2.0,length=1.2) #確定這種呼叫後才確定width和length是關鍵字參數
確定以上呼叫後,才確定width
和length
是關鍵字參數,並且關鍵字參數不必按照形參表的順序呼叫。
Java
和C++
在解決同一個函數但參數個數不同時,會使用函數過載的方法。Python使用可變參數的方法,非常靈活。
可變參數是指形參前帶有*
的變數,如下所示:
def foo(length,*others):
s = length
for para in others:
s *= para
return s
我們可以像下面 下麪這樣方便的呼叫:
foo(1.2,2.0,1.0) # 2.4
如上,帶一個星號的參數被傳參後,實際被解釋爲元組物件
。我們還可以這樣呼叫:
foo(1.2) # 1.2
總結完函數的參數後,再舉幾個Python內建的常用函數。
pow
大部分朋友應該知道pow
是個冪次函數,比如求:
pow(2,3)
除此以外,pow
還有第三個參數,使用更高效的演算法實現求冪後再求餘數:
pow(2,3,5) # 3
max,min
max,min用來求解最大最小值,實現relu
函數:
def relu(x):
return max(x,0)
sorted
sorted函數完成物件排序,它能接收一個指定排序規則的函數,完成定製排序。如下,根據字典值絕對值從小到大排序:
d = {'a':0,'b':-2,'c':1}
dr = sorted(d.items(),key=lambda x:abs(x[1]))
print(dr) # [('a', 0), ('c', 1), ('b', -2)]
Python有一個專門操作函數的模組:functools
,能實現一些關於函數的特殊操作。
偏函數固定函數的某些參數後,重新生成一個新的函數。
通常用法,當函數的參數個數太多,需要簡化時,使用partial
建立一個新的函數。
假設我們要經常呼叫int
函數轉換二進制字元,設定參數base
爲2:
int('1010',base=2)
爲了避免每次都寫一個參數base,我們重新定義一個函數:
def int2(s):
return int(s,base=2)
以後每次轉化字串時,只需int2('1010
)即可,更加簡便。
偏函數也能實現上述功能:
from functools import partial
intp = partial(int,base=2)
那麼有的朋友會問,偏函數就是個雞肋,重新定義的int2
更加直觀容易理解,這個角度講確實是這樣。但是int2
不能再接收base
參數,但是intp
函數還是能接收base
參數,依然保留了原來的參數:
intp('10',base=16) # 16
可能看到這裏的讀者還是有些迷糊,不太確定怎麼使用偏函數。可以先記住:修改內建函數的預設參數,就像內建函數int
預設參數base等於10,使用偏函數調整預設base值爲2.
遞回函數是指呼叫自身的函數。如下使用遞回反轉字串:
def reverseStr(s):
if not s:
return s
return reverseStr(s[1:])+s[0]
print(reverseStr('nohtyp')) # python
reverseStr
函數裏面又呼叫了函數reverseStr
,所以它是遞回函數。
使用遞回函數需要注意找到正確的遞回基,防止陷入無限遞回。
更多使用遞回的例子大家可參考此公衆號之前推播。
匿名函數是指使用lambda
關鍵字建立的函數。它的標準結構如下:
lambda 形參列表: 含有形參列表的表達式
表達式的計算值即爲lambda
函數的返回值。
如下lambda
函數:
lambda x,y: x+y
它等價於下面 下麪的f
函數:
def f(x,y):
return x+y
lambda函數常做爲max
,sorted
,map
,filter
等函數的key參數。
可以用來接收另一個函數作爲參數的函數叫做高階函數。
如下f
有一個參數g
,而g
又是函數,所以f
是高階函數:
def f(g):
g()
Python 中經常會遇到高階函數,今天介紹幾個內建的常用的高階函數。
map
map 函數第一個參數爲函數,它作用於列表中每個的元素。
如下,列表中的單詞未按照首字母大寫其他字元小寫的規則,使用map
一一capitalize
每個元素:
m = map(lambda s: s.capitalize(), ['python','Very','BEAUTIFUL'])
print(list(m))
結果:
['Python', 'Very', 'Beautiful']
reduce
reduce 高階函數實現化簡列表,它實現的效果如下:
如下例子,函數f
等於x+y
,求得兩數之和,然後再與第三個數相加,依次下去,直到列表尾部,進而得到整個列表的和:
from functools import reduce
def f(x,y):
return x+y
r = reduce(f, [1,3,2,4])
print(r) # 10
以上reduce
求解過程等於:
需要注意:reduce
函數要求f
必須帶2個參數,只有這樣才能 纔能完成歸約化簡。
巢狀函數是指裏面再巢狀函數的函數。
如下例子,將列錶轉化爲二元樹。已知列表nums
,
nums = [3,9,20,None,None,15,7],轉化爲下面 下麪二元樹:
二元樹定義:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
構建滿足以上結構的二元樹,可以觀察到:樹的父節點和左右子節點的關係:
基於以上公式,再使用遞回構建二元樹。
遞回基情況:
if index >= len(nums) or nums[index] is None:
return None
遞回方程:
根據以上分析,得到如下程式碼,list_to_binarytree
函數是巢狀函數,它裏面還有一個level
子函數:
def list_to_binarytree(nums):
def level(index):
if index >= len(nums) or nums[index] is None:
return None
root = TreeNode(nums[index])
root.left = level(2 * index + 1)
root.right = level(2 * index + 2)
return root
return level(0)
binary_tree = list_to_binarytree([3,9,20,None,None,15,7])
通常使用巢狀函數的場景:實現一個功能只需要編寫2個函數,寫成一個class
好像顯得有些不必要,寫成巢狀後更簡潔,並且某些參數能共用,親和性會更好。不妨體會上面的nums
參數。
函數專題主要總結了以下:
Python 函數專題
基礎部分
1 函陣列成
2 參照傳參
3 預設參數與關鍵字參數
4 可變參數
5 內建函數
進階部分
6 偏函數
7 遞回函數
8 匿名函數
9 高階函數
10 巢狀函數