Python小白學習之路(十四)—【作用域】【匿名函式】【程式設計方法論】【高階函式】
吧啦吧啦內心戲
在沒有具體學作用域之前,我在之前的學習筆記中就有提到
我開始以為是自己自創的詞兒
沒想到這個詞早已經存在(手動捂臉)
真是個無知的小火鍋(不知者無罪)
我發現自己最擅長做的事情,就是給自己找個臺階,然後很快順勢滑下來
一、作用域
先來一段程式碼分析一波吧
1 name = 'xhg' 2 def name1(): 3 name = 'aa' 4 def name2(): 5 name = 'bb' 6 print(name) 7 return name2 8 a = name1()9 print(a) 10 a() #執行結果 <function name1.<locals>.name2 at 0x004D94B0> bb
有很多人會有疑問,最後一行程式碼 a() 的作用域是第一層,我在之前的學習筆記中也是這麼理解的
既然他的作用域是第一層,則執行 print(name) 的時候,結果不應該是 xhg 嗎?怎麼是 bb
原來我之前對作用域的理解有些誤會
''' #分析程式碼執行過程 1.name = 'xhg' 定義全域性變數 2.def name1(): 定義了函式name1,在記憶體中開闢了空間,但函式內部具體內容不執行 3.a = name1() 執行name1函式,並將其結果賦值給變數a 4.name = 'aa' 定義了局部變數 5.def name2(): 定義了函式nam2,在記憶體中開闢了空間,但函式內部具體內容不執行 6.return name2 返回一個函式name2,則返回函式的執行結果,該結果為name2的記憶體地址,所以變數a的值為name2的記憶體地址 7.a() 實質為執行函式name2 8.name = 'bb' 定義了局部變數 9.print(name) 在該作用域中找變數的值,所以列印結果為 bb'''
結論:
- 函式的執行與其申明定義的作用域有關,與其執行的作用域(呼叫的)無關
- 函式一旦定義成功,其相對作用域已經確定
- 所以在上一段程式程式碼中,a() 雖然和 name = 'xhg' 看上去為一個作用域,但實質上,a() 的作用域為函式 name2
- return +函式名 返回的是該函式的記憶體地址
- eg. renturn name1
- return +函式名() 遞迴呼叫
- eg. renturn name1()
- eg. renturn name1()
- 對於一個函式的執行結果其實就是return返回的值
再看兩段程式碼
#程式碼一: name = 'xhg' def name1(): name = 'aa' def name2(): name = 'bb' def name3(): name = 'cc' print(name) return name3 return name2 a = name1() b = a() print(b()) #程式碼二: name = 'xhg' def name1(): name = 'aa' def name2(): name = 'bb' def name3(): name = 'cc' print(name) return name3 return name2 print(name1()()()) #執行結果相同,都為 cc None
說明 print(name1()()()) 等同於 a = name1() ;b = a() ;print(b())
二、匿名函式
語法結構(由四部分構成):lambda關鍵字 + 匿名函式的形參 + 冒號:+ 該函式的操作(子程式碼)
- 第四部分的作用相當於return,直接返回了一個值
- 不可以是複雜的邏輯判斷,直接來個操作就ok了
- 載入完之後釋放,需要儲存就附一個值
- 匿名函式與其他函式聯合使用,通常情況下不會單獨存在
關鍵字 lambda
- 用來標識匿名函式
def calc(x): return x + 1 a = calc(10) print(a)
用匿名函式來實現上述程式的功能
a = lambda x : x + 1 print(a(10))
如果形參為多個引數,應該用括號將匿名函式的第四部分括起來
(因為在使用return返回多個引數時,系統預設加了括號)
def test(x,y,z): return x + 1, y + 1, z + 1 a = test(1,2,3) print(a)
用匿名函式來實現上述程式的功能
a = lambda x, y, z : (x + 1, y + 1, z + 1) #如果不加括號會報錯 print(a(1, 2, 3))
三、程式設計的方法論
有三種,分別是:面向過程程式設計、函數語言程式設計、函數語言程式設計
面向過程程式設計
- 是一種以事件為中心的程式設計思想。
- 就是分析出解決問題的步驟,然後用方法(函式)去實現這些步驟
- 使用的時候按照步驟順序依次呼叫。
- 面對要實現的功能,找到解決問題的入口,按照一個固定的流程去模擬解決問題的流程
- 面向過程是一種自頂向下的程式設計
函數語言程式設計
- 就是先定義一個數學函式,按照數學模型用程式語言去實現它
舉例:現在有這樣一個數學表示式:y = 2 * x + 1
#面向過程式的程式設計: def cal(x): a = 2 * x a += 1 return a print(cal(10)) #函數語言程式設計: def cal(x): return 2 * x + 1 print(cal(10))
面向物件程式設計
- 是一種線性的思維。
- 與面向過程是相輔相成的。
- 面向物件就是將構成問題的事務分解抽象成各個物件。
- 建立物件的目的不是為了完成某個步驟,而是敘述某個事務在整個解決問題的步驟中的行為。
- 面向物件是將事物高度抽象化。
四、高階函式
定義(滿足其中一個條件即可)
- 函式接受的引數是一個函式名
- 返回值中包含函式
舉例一:函式接受的引數是一個函式名
def name1(n): #n的值為函式name2的返回值none,所以不是高階函式 print(n) def name2(name): print('my name is %s' %name) name1(name2('xhg')) #執行結果 my name is xhg None def name1(n): #n的值為函式name2,所以是高階函式 print(n) def name2(name): print('my name is %s' %name) name1(name2) #執行結果 <function name2 at 0x021594B0>
舉例二:返回值中包含函式
def name1(): print('from name1') def name2(): print('from name2') return name1 #返回值中包含函式,所以為高階函式 n = name2() n() #執行結果 from name2 from name1 def name1(): print('from name1') def name2(): print('from name2') return name1() #遞迴呼叫 n = name2() print(n) #執行結果 from name2 from name1 None
由於 return name1 和 return name1() 就差一個括號,導致結果不同
雖然差別小,可是有本質的區別,要注意
return name1 是將函式name1的地址賦值給n
return name1() 必須先執行函式name1,將函式name1執行結束後的值由return返回給n(函式name無返回值,所以其結果為none)
寫在後面的話:
今天下午有點累
中午沒有休息好
長大以後,才發現一個人能做到換位思考真的不是很容易
保持一顆善良的心看待這個世界
因為抱怨會讓自己變得消極
全世界我最可愛(自己鼓勵自己唄,開開心心才能好好學習)