1. 程式人生 > >Python小白學習之路(十四)—【作用域】【匿名函式】【程式設計方法論】【高階函式】

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()
  • 對於一個函式的執行結果其實就是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)

 

寫在後面的話:

今天下午有點累

中午沒有休息好

長大以後,才發現一個人能做到換位思考真的不是很容易

保持一顆善良的心看待這個世界

因為抱怨會讓自己變得消極

全世界我最可愛(自己鼓勵自己唄,開開心心才能好好學習)