python函式(全域性變數,區域性變數,作用域,遞迴函式,高階函式,匿名函式)
1.1函式
1.1.1什麼是函式
函式就是程式實現模組化的基本單元,一般實現某一功能的集合。
函式名:就相當於是程式程式碼集合的名稱
引數:就是函式運算時需要參與運算的值被稱作為引數
函式體:程式的某個功能,進行一系列的邏輯運算
return 返回值:函式的返回值能表示函式的執行結果或執行狀態。
1.1.2函式的作用
- 函式是組織好的,可重複使用的,用來實現單一,或者相關功能的程式碼。
- 函式能夠提高應用的模組性,和程式碼的重複利用率
我們已近知道python提供了許多內建函式,比如print(),我們自已建立的函式稱為內建函式
1.1.3定義函式的語法
def 函式名(引數): 函式體 return 返回值內容
1.1.4函式定義規則
- 函式程式碼以def關鍵詞開頭,後接定義函式的名稱和圓括號,冒號():
- 函式內容以冒號":"開始,並且縮排
- 函式內容的第一行內容可選擇性使用文件字串---用來定義該函式的說明
- 函式的返回值: return [返回值內容] 用於結束函式,返回一個值,表示程式執行的結果。
- 函式不帶return 預設返回None 返回值可以是任何型別的資料(數字,字串,函式,列表,元祖,字典等),也可以是一個表示式
- 函式引數:任何傳入引數和自變數必須放在圓括號中間,圓括號之間用於定義引數。
1.1.5函式呼叫
定義函式語法
def printinfo(): print("hello world") return
呼叫函式
printinfo() #函式執行結果 hello world
檢視函式返回值
print(printinfo()) #結果 hello world None #預設函式值返回類容
其他返回值示例
def printinfo(): print("hello world") return [111+222] print(printinfo()) #結果 hello world [333] #返回值內容
1.1.5函式引數
注:形參和實參(定義函式時,圓括號(引數)中的所有引數都是形式引數也稱為形參,呼叫函式中,圓括號(引數)中的引數稱為實際引數,也叫實參)
1)必須引數::
2)關鍵字引數:
3)預設引數:
4)可變引數(*args,**kwargs):
1.必須引數:
從字面理解:必須要傳入引數
傳入的引數:與定義的形參順序一一對應
def stuinfo(name,age): print(name,age) return #在不傳入引數 stuinfo() #呼叫函式 #函式執行結果 TypeError: stuinfo() missing 2 required positional arguments: 'name' and 'age' #報錯,提示型別錯誤,該函式,缺少兩個位置引數不傳入引數
def stuinfo(name,age): print(name,age) return stuinfo("zhangsan",18) #函式執行結果 zhangsan 18傳入引數
2.關鍵字引數
def stuinfo(name,age,hobby): print(name,age,hobby) return #引數位置匹配,關鍵字引數,與形參的位置順序無關, stuinfo(age=19,name="lisi",hobby="run") #name= age= hobby=就是關鍵字引數 #函式執行結果 lisi 19 run關鍵字引數
3.預設引數
預設引數必須指向不變的物件
當函式有多個引數,把變化大的引數反正前面,變化小的引數放在後面。變化小的引數就作為預設引數。
預設引數好處:降低呼叫函式的難度
#預設引數,可以直接使用用,也可以修改預設引數值 def grade(name,age,city="BeiJing"): #city="BeiJing" 就是預設引數 print(name,age,city) # grade("yangjian",age=18) grade("lala",age=18,city="shanghai") #grade函式執行結果 lala 18 shanghai預設引數
4.可變引數
*args **args
用途:在定義函式需要,每個定義函式功能的都可以繼續優化,所以我們需要用動態引數
如果把引數寫死了,後期繼續修改完善的功能的,修改該函式功能則會相當麻煩
*args 結果型別是元祖,傳遞值是任意型別
def test(*args): print(args) test(123456,[12,45,88],{"name":"qw","age":15}) #可以傳遞任意引數的型別 #函式執行結果 (123456, [12, 45, 88], {'name': 'qw', 'age': 15})
**kwargs結果型別是字典,傳遞值是以key=value方式傳入
def test1(**kwargs): print(kwargs) test1(name="xiha",age="12") #執行結果 {'age': '12', 'name': 'xiha'}
函式* 和 ** 解包
#* def test(*args): print(args) test(*[1,2,3,4,5,6,7,8,9]) #*引數解包,把【元素】 迴圈出來,新增到元祖中 #結果 (1, 2, 3, 4, 5, 6, 7, 8, 9)*
def test1(**kwargs): print(kwargs) test1(**{"hobby":456,"number":789}) #**引數解包,把key:value 迴圈出來,新增到字典中 #結果 {'number': 789, 'hobby': 456}**
函式引數組合
def f2(a, b, c=0,*args,**kwargs): print('a =', a, 'b =', b, 'c =', c, args,kwargs) f2(12,b=12,c=89,aa="as",bb="xxx") #結果 a = 12 b = 12 c = 89 () {'bb': 'xxx', 'aa': 'as'}
函式引數總結:
1.形參的位置順序,必須與實參的順序一一對應,缺一不行,多一不行
2.關鍵字引數,無須一一對應,缺一不行,多一不行
3.位置引數必須在關鍵字引數左邊
4.預設引數一定要用不可變物件,如果是可變物件,程式執行時會有邏輯錯誤
1.2全域性變數和區域性變數
在子程式中定義的變數稱為區域性變數,只在子程式內部生效,
在程式一開始定義的變數稱為全域性變數
全域性變數作用域是整個程式,區域性變數作用域是定義該變數的子程式。
當全域性變數與區域性變數同名時:在定義區域性變數的子程式內,區域性變數起作用,在其他地方全域性變數起作用
name = "xixi" #全域性變數 def change_name(): name = "haha" #區域性變數只在函式區域性作用域內生效 print("我的名字",name) return change_name() print(name) def me(): global name #宣告name是全域性變數 global name = "yj" #修改name全域性變數的值 print(name) return me()
如果全域性變數是可變的資料型別,函式可以對全域性變數內部直接進行修改
eng = ["merry","jack","petter"] def chang(): eng.append("mali") print(eng) return chang()
總結:
一般寫程式變數的命名規則
###全域性變數變數名大寫
###區域性變數變數名小寫
- 函式優先讀取區域性變數,能讀全域性變數,無法對全域性變數重新賦值操作,#全域性變數是不可變的型別
- 全域性變數是可變型別,函式可以對全域性變數進行操作
- 函式中有global關鍵字,變數本質就是全域性變數,可讀取全域性變數,也可操作全域性變數
1.3函式之間巢狀
name = "YangJIan" #最外層 def change_name(): #第二層 name = "YangJIan2" def change_name2(): #第三層 name = "YangJIan3" print("第3層列印", name) change_name2() # 呼叫內層函式 print("第2層列印", name) change_name() #先執行區域性函式的列印, print("最外層列印", name) # 第3層列印 YangJIan3 # 第2層列印 YangJIan2 # 最外層列印 YangJIan
注:多層函式巢狀,子級函式,只在子級函式內部生效。父級函式能呼叫子級函式的功能
1.4遞迴函式
1.在函式內部,可以呼叫其他函式,如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式。
2.在使用遞迴策越是,必須有一個明確的敵對結束條件,稱為遞迴出口
函式呼叫的時候,每次呼叫時要做地址儲存,引數傳遞等。
如果函式包含了對其自身函式的呼叫,該函式就是遞迴。如下
def foo(n): #實現階乘 if n == 1: return n # 當滿種條件n==1才執行return 操作 res = n*foo(n-1) #呼叫自已本身的函式的結果(再判斷條件是否滿足條件)給res , return res print(foo(5)) #120
遞迴演算法所所體現的重複一般有的要求:
1.每次呼叫在上次規模上都有有所減小:
2.每次遞迴呼叫都是有明確條件的。
3.相領兩次的重複之間有緊密的聯絡,前一次要為後一次做準備(通常前一次的輸出(返回值結果))就作為後一次的輸入;
4.在問題的規模得到滿足條件時,而不再進行遞迴呼叫。
1.5函數語言程式設計
面向過程程式設計:我們通過把大段程式碼拆成函式,通過一層一層的函式,可以把複雜的任務分解成簡單的任務,這種一步一步的分解可以稱之為面向過程的程式設計。函式就是面向過程的程式設計的基本單元。
函數語言程式設計:是使用一系列函式去解決問題,函數語言程式設計就是根據程式設計的正規化來的出想要的結果,只要是輸入時確定的,輸出就是確定的。
1.6高階函式
能把函式作為引數傳入,這樣的函式就稱為高階函式。
回到頂部1.6.1函式即變數
以python的內建函式print()為列,呼叫該函式一下程式碼
>>> print("hello world") hello world #只寫print >>> print <built-in function print> #可見print("hello world")是函式呼叫,而print是函式本身
要獲得函式呼叫執行的結果,我們把結果賦值給變數:
>>> aa = abs(-20) >>> aa 20
如果把函式本身賦值給變數
>>> p = print >>> p <built-in function print> #函式本身可以賦值給變數,變數可以指向函式
我們通過變數來呼叫這個print函式,驗證結果如下
>>> p("check") check
總結:函式名也是變數,對於print()這個內建函式,完全可以把函式名print看成變數,它指向一個可以列印任何東西的函式
注:實際程式程式碼絕不能這麼寫,上面只是為了舉例說明,要恢復print函式,請重啟python的互動環境
回到頂部1.6.2傳入函式
變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一函式作為函式,這種函式就稱為高階函式,
函式的返回值是一個函式名,也是高階函式。
例如:一個簡單的高階函式
def add(x,y,z): return abs(x)+abs(y) aa = add(12,23,abs) #函式執行的結果 賦值給 aa print(aa) #檢視aa的值 #35 #注,abs()函式是求一個整數的絕對值
1.7匿名函式
什麼是匿名函式:
在python中有一個匿名函式lambda,匿名函式就是指:無需定義識別符號(函式名)的函式或子程式。
定義lambda表示式:
lambda arguments:express #arguments 引數(可以有多個引數) #express 表示式 #lambda返回值是一個函式的地址,也就是函式物件 aa = lambda arguments:express #把的到lambda函式地址,賦值給變數aa 檢視這個lambda函式地址 ,用aa(argument) 檢視這個函式的值
例1
def pf(x=0): return x**2 print(pf(3))普通函式定義,求數字平方
aa = lambda x:x**2 print(aa(4)) #16lambda函式,求數字平方
總結:
1.lambda函式可以引數可以有多個,包含的表示式不能超過一個,不要試圖向lambda函式中塞入太多東西,如果你需要做複雜的功能,應該定義一個普通函式,想定義什麼就定義什麼。
2.lambda函式用在需要封裝特殊的,非重用程式碼上,避免令我們的程式碼充斥大量的單行函式。
map函式
map()函式,map對映
map(func,iterable)
map()函式接受兩個引數,一個是函式,一個可迭代的物件(iterable),map將傳入的函式依次作用到序列的每個元素,並把結果作為新的 可迭代的物件 的結果返回
例:有個函式,f(x) = x+1 把得到的數字 加1 要把這個函式作用在一個[1,2,3,4,5,6]上
number = [1,2,3,4,5,6] #1.用普通函式定義方法 def add_one(x): return x+1 def map_test(func,arrey): res = [] for i in arrey: i = func(i) res.append(i) return res print(map_test(add_one,number)) #[2, 3, 4, 5, 6, 7] #2.用lambda函式定義的得到結果,藉助1定義的map_test函式 print(map_test(lambda x:x+1,number)) #[2, 3, 4, 5, 6, 7] #3.用map()本身函式去定義 print(list(map(lambda x:x+1 ,number))) #[2, 3, 4, 5, 6, 7] #注:map()得出的結果是一個iterator ,需要用list()函式讓它個整個序列都計算出來返回一個list
我們可能會想,寫一個迴圈,也可以計算出結果,但要實現多個功能,是不是也要寫多個迴圈 例:得出每個列表中元素的平方或則n次方
map()作為高階函式,事實上把運算規則抽象了,不但可以計算簡單的 f(x) = x+1 ,也能計算更復雜的函式。
總結:map() 處理序列中的每個元素,得到的結果是一個 iterator ,需通過list(iteratro),該list元素個數,與原來位置一樣
reduce函式
在python2可以直接用reduce()函式
在python3需要呼叫reduce模組
from functools import reduce reduce(function, sequence, initial=None) #該函式的預設用法
reduce函式,將function作用sequence序列的元素,每次攜帶一對(先前的結果以及下一序列的元素),連續的將現有的結果和下一個作用在獲得的隨後的結果上,最後得到我們的序列為一個最終結果的返回值
number1 = [2,3,4,10] #1.普通函式定義 def chengfa(x,y): return x*y #返回得到兩個數相乘的結果 def reduce_test(func,seq,init=None): if init is None: res = seq.pop(0) #seq刪除第一個元素,並獲取刪除這個元素 賦值給res else: res = init for i in seq: res = func(res,i) #迴圈一次,執行func這個函式 return res print(reduce_test(chengfa,number1)) #240 print(reduce_test(chengfa,number1,10)) #2400 #如果給了init 初始值,就是從初始值 乘以列表的每個元素的的出結果 #2.lambda函式,藉助reduce_test()函式定義 print(reduce_test(lambda x,y:x*y,number1,init=3)) #720 #3.使用reduce(),結合lambda() print(reduce(lambda x,y:x*y, number1)) #240 得到列表所有元素,相乘的結果 number1 = [2,3,4,10] #1.普通函式定義 def chengfa(x,y): return x*y #返回得到兩個數相乘的結果 def reduce_test(func,seq,init=None): if init is None: res = seq.pop(0) #seq刪除第一個元素,並獲取刪除這個元素 賦值給res else: res = init for i in seq: res = func(res,i) #迴圈一次,執行func這個函式 return res print(reduce_test(chengfa,number1)) #240 print(reduce_test(chengfa,number1,10)) #2400 #如果給了init 初始值,就是從初始值 乘以列表的每個元素的的出結果 #2.lambda函式,藉助reduce_test()函式定義 print(reduce_test(lambda x,y:x*y,number1,init=3)) #720 #3.使用reduce(),結合lambda() from functools import reduce print(reduce(lambda x,y:x*y, number1)) #240得到列表所有元素,相乘的結果
print(reduce(lambda x,y:x+y,range(1,101)))得到1-100的和
filter函式
filter()函式用於過濾序列
和map()類似,filter()也接受一個函式和一個序列(可迭代的物件,也就是能被for迴圈),和map()不同的是,fillter()把傳入的函式依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。
例:
aa = ['A', '', 'B', None, 'C', ' '] #1.自定義函式測試 def not_empty(s): return s and s.strip() def filter_test(func,iter): res = [] for i in iter: i = func(i) if i: res.append(i) return res print(filter_test(not_empty,aa)) #['A', 'B', 'C'] #2.filter內建函式測試 print(list(filter(not_empty,aa))) #['A', 'B', 'C']把列表中空字串,空元素,都去掉
filter()這個函式,關鍵在於正確實現一個篩選函式,
注:filter()函式返回的是一個iterator,記憶體地址,需要看記憶體地址的值, 用list()函式或得該地址的值
sorted函式
sorted()函式也是一個高階函式,它可以接收key
sorted排序,排序是比較元素的大小,如果是數字可以直接比較,如果是字串或則兩個dict(字典)?
sorted()傳入的引數是可迭代的物件,返回值的物件是一個列表
例:
aa = [11,-10,20,21,30,-40] print(sorted(aa))數字預設排序
接收一個key函式來實現自定義排序
例:根據絕對值大小來進行排序
aa = [11,-10,20,21,30,-40] print(sorted(aa,key=abs)) #[-10, 11, 20, 21, 30, -40]根據絕對值排序
例:字串排序
print(sorted("hello")) #['e', 'h', 'l', 'l', 'o'] print(sorted(["hello","ho","haha"])) # ['haha', 'hello', 'ho']字串排序
注:預設情況下,對字串排序是按照ASCII編碼表的大小進行比較的
最後總結:
python內建的幾個高階函式:map() ,reduce(),filter,sorted()
1.1函式
1.1.1什麼是函式
函式就是程式實現模組化的基本單元,一般實現某一功能的集合。
函式名:就相當於是程式程式碼集合的名稱
引數:就是函式運算時需要參與運算的值被稱作為引數
函式體:程式的某個功能,進行一系列的邏輯運算
return 返回值:函式的返回值能表示函式的執行結果或執行狀態。
1.1.2函式的作用
- 函式是組織好的,可重複使用的,用來實現單一,或者相關功能的程式碼。
- 函式能夠提高應用的模組性,和程式碼的重複利用率
我們已近知道python提供了許多內建函式,比如print(),我們自已建立的函式稱為內建函式
1.1.3定義函式的語法
def 函式名(引數): 函式體 return 返回值內容
1.1.4函式定義規則
- 函式程式碼以def關鍵詞開頭,後接定義函式的名稱和圓括號,冒號():
- 函式內容以冒號":"開始,並且縮排
- 函式內容的第一行內容可選擇性使用文件字串---用來定義該函式的說明
- 函式的返回值: return [返回值內容] 用於結束函式,返回一個值,表示程式執行的結果。
- 函式不帶return 預設返回None 返回值可以是任何型別的資料(數字,字串,函式,列表,元祖,字典等),也可以是一個表示式
- 函式引數:任何傳入引數和自變數必須放在圓括號中間,圓括號之間用於定義引數。
1.1.5函式呼叫
定義函式語法
def printinfo(): print("hello world") return
呼叫函式
printinfo() #函式執行結果 hello world
檢視函式返回值
print(printinfo()) #結果 hello world None #預設函式值返回類容
其他返回值示例
def printinfo(): print("hello world") return [111+222] print(printinfo()) #結果 hello world [333] #返回值內容
1.1.5函式引數
注:形參和實參(定義函式時,圓括號(引數)中的所有引數都是形式引數也稱為形參,呼叫函式中,圓括號(引數)中的引數稱為實際引數,也叫實參)
1)必須引數::
2)關鍵字引數:
3)預設引數:
4)可變引數(*args,**kwargs):
1.必須引數:
從字面理解:必須要傳入引數
傳入的引數:與定義的形參順序一一對應
def stuinfo(name,age): print(name,age) return #在不傳入引數 stuinfo() #呼叫函式 #函式執行結果 TypeError: stuinfo() missing 2 required positional arguments: 'name' and 'age' #報錯,提示型別錯誤,該函式,缺少兩個位置引數不傳入引數
def stuinfo(name,age): print(name,age) return stuinfo("zhangsan",18) #函式執行結果 zhangsan 18傳入引數
2.關鍵字引數
def stuinfo(name,age,hobby): print(name,age,hobby) return #引數位置匹配,關鍵字引數,與形參的位置順序無關, stuinfo(age=19,name="lisi",hobby="run") #name= age= hobby=就是關鍵字引數 #函式執行結果 lisi 19 run關鍵字引數
3.預設引數
預設引數必須指向不變的物件
當函式有多個引數,把變化大的引數反正前面,變化小的引數放在後面。變化小的引數就作為預設引數。
預設引數好處:降低呼叫函式的難度
#預設引數,可以直接使用用,也可以修改預設引數值 def grade(name,age,city="BeiJing"): #city="BeiJing" 就是預設引數 print(name,age,city) # grade("yangjian",age=18) grade("lala",age=18,city="shanghai") #grade函式執行結果 lala 18 shanghai預設引數
4.可變引數
*args **args
用途:在定義函式需要,每個定義函式功能的都可以繼續優化,所以我們需要用動態引數
如果把引數寫死了,後期繼續修改完善的功能的,修改該函式功能則會相當麻煩
*args 結果型別是元祖,傳遞值是任意型別
def test(*args): print(args) test(123456,[12,45,88],{"name":"qw","age":15}) #可以傳遞任意引數的型別 #函式執行結果 (123456, [12, 45, 88], {'name': 'qw', 'age': 15})
**kwargs結果型別是字典,傳遞值是以key=value方式傳入
def test1(**kwargs): print(kwargs) test1(name="xiha",age="12") #執行結果 {'age': '12', 'name': 'xiha'}
函式* 和 ** 解包
#* def test(*args): print(args) test(*[1,2,3,4,5,6,7,8,9]) #*引數解包,把【元素】 迴圈出來,新增到元祖中 #結果 (1, 2, 3, 4, 5, 6, 7, 8, 9)*
def test1(**kwargs): print(kwargs) test1(**{"hobby":456,"number":789}) #**引數解包,把key:value 迴圈出來,新增到字典中 #結果 {'number': 789, 'hobby': 456}**
函式引數組合
def f2(a, b, c=0,*args,**kwargs): print('a =', a, 'b =', b, 'c =', c, args,kwargs) f2(12,b=12,c=89,aa="as",bb="xxx") #結果 a = 12 b = 12 c = 89 () {'bb': 'xxx', 'aa': 'as'}
函式引數總結:
1.形參的位置順序,必須與實參的順序一一對應,缺一不行,多一不行
2.關鍵字引數,無須一一對應,缺一不行,多一不行
3.位置引數必須在關鍵字引數左邊
4.預設引數一定要用不可變物件,如果是可變物件,程式執行時會有邏輯錯誤
1.2全域性變數和區域性變數
在子程式中定義的變數稱為區域性變數,只在子程式內部生效,
在程式一開始定義的變數稱為全域性變數
全域性變數作用域是整個程式,區域性變數作用域是定義該變數的子程式。
當全域性變數與區域性變數同名時:在定義區域性變數的子程式內,區域性變數起作用,在其他地方全域性變數起作用
name = "xixi" #全域性變數 def change_name(): name = "haha" #區域性變數只在函式區域性作用域內生效 print("我的名字",name) return change_name() print(name) def me(): global name #宣告name是全域性變數 global name = "yj" #修改name全域性變數的值 print(name) return me()
如果全域性變數是可變的資料型別,函式可以對全域性變數內部直接進行修改
eng = ["merry","jack","petter"] def chang(): eng.append("mali") print(eng) return chang()
總結:
一般寫程式變數的命名規則
###全域性變數變數名大寫
###區域性變數變數名小寫
- 函式優先讀取區域性變數,能讀全域性變數,無法對全域性變數重新賦值操作,#全域性變數是不可變的型別
- 全域性變數是可變型別,函式可以對全域性變數進行操作
- 函式中有global關鍵字,變數本質就是全域性變數,可讀取全域性變數,也可操作全域性變數
1.3函式之間巢狀
name = "YangJIan" #最外層 def change_name(): #第二層 name = "YangJIan2" def change_name2(): #第三層 name = "YangJIan3" print("第3層列印", name) change_name2() # 呼叫內層函式 print("第2層列印", name) change_name() #先執行區域性函式的列印, print("最外層列印", name) # 第3層列印 YangJIan3 # 第2層列印 YangJIan2 # 最外層列印 YangJIan
注:多層函式巢狀,子級函式,只在子級函式內部生效。父級函式能呼叫子級函式的功能
1.4遞迴函式
1.在函式內部,可以呼叫其他函式,如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式。
2.在使用遞迴策越是,必須有一個明確的敵對結束條件,稱為遞迴出口
函式呼叫的時候,每次呼叫時要做地址儲存,引數傳遞等。
如果函式包含了對其自身函式的呼叫,該函式就是遞迴。如下
def foo(n): #實現階乘 if n == 1: return n # 當滿種條件n==1才執行return 操作 res = n*foo(n-1) #呼叫自已本身的函式的結果(再判斷條件是否滿足條件)給res , return res print(foo(5)) #120
遞迴演算法所所體現的重複一般有的要求:
1.每次呼叫在上次規模上都有有所減小:
2.每次遞迴呼叫都是有明確條件的。
3.相領兩次的重複之間有緊密的聯絡,前一次要為後一次做準備(通常前一次的輸出(返回值結果))就作為後一次的輸入;
4.在問題的規模得到滿足條件時,而不再進行遞迴呼叫。
1.5函數語言程式設計
面向過程程式設計:我們通過把大段程式碼拆成函式,通過一層一層的函式,可以把複雜的任務分解成簡單的任務,這種一步一步的分解可以稱之為面向過程的程式設計。函式就是面向過程的程式設計的基本單元。
函數語言程式設計:是使用一系列函式去解決問題,函數語言程式設計就是根據程式設計的正規化來的出想要的結果,只要是輸入時確定的,輸出就是確定的。
1.6高階函式
能把函式作為引數傳入,這樣的函式就稱為高階函式。
回到頂部1.6.1函式即變數
以python的內建函式print()為列,呼叫該函式一下程式碼
>>> print("hello world") hello world #只寫print >>> print <built-in function print> #可見print("hello world")是函式呼叫,而print是函式本身
要獲得函式呼叫執行的結果,我們把結果賦值給變數:
>>> aa = abs(-20) >>> aa 20
如果把函式本身賦值給變數
>>> p = print >>> p <built-in function print> #函式本身可以賦值給變數,變數可以指向函式
我們通過變數來呼叫這個print函式,驗證結果如下
>>> p("check") check
總結:函式名也是變數,對於print()這個內建函式,完全可以把函式名print看成變數,它指向一個可以列印任何東西的函式
注:實際程式程式碼絕不能這麼寫,上面只是為了舉例說明,要恢復print函式,請重啟python的互動環境
回到頂部1.6.2傳入函式
變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一函式作為函式,這種函式就稱為高階函式,
函式的返回值是一個函式名,也是高階函式。
例如:一個簡單的高階函式
def add(x,y,z): return abs(x)+abs(y) aa = add(12,23,abs) #函式執行的結果 賦值給 aa print(aa) #檢視aa的值 #35 #注,abs()函式是求一個整數的絕對值
1.7匿名函式
什麼是匿名函式:
在python中有一個匿名函式lambda,匿名函式就是指:無需定義識別符號(函式名)的函式或子程式。
定義lambda表示式:
lambda arguments:express #arguments 引數(可以有多個引數) #express 表示式 #lambda返回值是一個函式的地址,也就是函式物件 aa = lambda arguments:express #把的到lambda函式地址,賦值給變數aa 檢視這個lambda函式地址 ,用aa(argument) 檢視這個函式的值
例1
def pf(x=0): return x**2 print(pf(3))普通函式定義,求數字平方
aa = lambda x:x**2 print(aa(4)) #16lambda函式,求數字平方
總結:
1.lambda函式可以引數可以有多個,包含的表示式不能超過一個,不要試圖向lambda函式中塞入太多東西,如果你需要做複雜的功能,應該定義一個普通函式,想定義什麼就定義什麼。
2.lambda函式用在需要封裝特殊的,非重用程式碼上,避免令我們的程式碼充斥大量的單行函式。
map函式
map()函式,map對映
map(func,iterable)
map()函式接受兩個引數,一個是函式,一個可迭代的物件(iterable),map將傳入的函式依次作用到序列的每個元素,並把結果作為新的 可迭代的物件 的結果返回
例:有個函式,f(x) = x+1 把得到的數字 加1 要把這個函式作用在一個[1,2,3,4,5,6]上
number = [1,2,3,4,5,6] #1.用普通函式定義方法 def add_one(x): return x+1 def map_test(func,arrey): res = [] for i in arrey: i = func(i) res.append(i) return res print(map_test(add_one,number)) #[2, 3, 4, 5, 6, 7] #2.用lambda函式定義的得到結果,藉助1定義的map_test函式 print(map_test(lambda x:x+1,number)) #[2, 3, 4, 5, 6, 7] #3.用map()本身函式去定義 print(list(map(lambda x:x+1 ,number))) #[2, 3, 4, 5, 6, 7] #注:map()得出的結果是一個iterator ,需要用list()函式讓它個整個序列都計算出來返回一個list
我們可能會想,寫一個迴圈,也可以計算出結果,但要實現多個功能,是不是也要寫多個迴圈 例:得出每個列表中元素的平方或則n次方
map()作為高階函式,事實上把運算規則抽象了,不但可以計算簡單的 f(x) = x+1 ,也能計算更復雜的函式。
總結:map() 處理序列中的每個元素,得到的結果是一個 iterator ,需通過list(iteratro),該list元素個數,與原來位置一樣
reduce函式
在python2可以直接用reduce()函式
在python3需要呼叫reduce模組
from functools import reduce reduce(function, sequence, initial=None) #該函式的預設用法
reduce函式,將function作用sequence序列的元素,每次攜帶一對(先前的結果以及下一序列的元素),連續的將現有的結果和下一個作用在獲得的隨後的結果上,最後得到我們的序列為一個最終結果的返回值
number1 = [2,3,4,10] #1.普通函式定義 def chengfa(x,y): return x*y #返回得到兩個數相乘的結果 def reduce_test(func,seq,init=None): if init is None: res = seq.pop(0) #seq刪除第一個元素,並獲取刪除這個元素 賦值給res else: res = init for i in seq: res = func(res,i) #迴圈一次,執行func這個函式 return res print(reduce_test(chengfa,number1)) #240 print(reduce_test(chengfa,number1,10)) #2400 #如果給了init 初始值,就是從初始值 乘以列表的每個元素的的出結果 #2.lambda函式,藉助reduce_test()函式定義 print(reduce_test(lambda x,y:x*y,number1,init=3)) #720 #3.使用reduce(),結合lambda() print(reduce(lambda x,y:x*y, number1)) #240 得到列表所有元素,相乘的結果 number1 = [2,3,4,10] #1.普通函式定義 def chengfa(x,y): return x*y #返回得到兩個數相乘的結果 def reduce_test(func,seq,init=None): if init is None: res = seq.pop(0) #seq刪除第一個元素,並獲取刪除這個元素 賦值給res else: res = init for i in seq: res = func(res,i) #迴圈一次,執行func這個函式 return res print(reduce_test(chengfa,number1)) #240 print(reduce_test(chengfa,number1,10)) #2400 #如果給了init 初始值,就是從初始值 乘以列表的每個元素的的出結果 #2.lambda函式,藉助reduce_test()函式定義 print(reduce_test(lambda x,y:x*y,number1,init=3)) #720 #3.使用reduce(),結合lambda() from functools