Python函數篇 -遞歸函數、匿名函數及高階...

1.全局變量和局部變量

  一般定義在程序的最開始的變量稱爲函數變量,在子程序中定義的變量稱爲局部變量,可以簡單的理解爲,無縮進的爲全局變量,有縮進的是局部變量,全局變量的作用域是整個程序,而局部變量的作用域是子程序內部,當程序運行時,首先會找程序內部有沒有局部變量,如果有,則調用,如果沒有,纔會去調用全局變量。如下:
[AppleScript] 純文本查看 複製代碼
1
2
3
4
5
6
7
8
9
複製代碼
name="czp"            #全局變量
def func():
    name="czp1"         #局部變量
    print(name)
func()
運行結果:
czp1              調用func()函數,程序會先在函數內部找有沒有name這個變量,如果有,就會調用該name的值,而如果沒有定義局部變量的話,函數會去找全局name
複製代碼


 

  可以通過global關鍵字,通過局部變量修改全局變量,如下所示:
[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
複製代碼
name="czp"          #定義全局變量
def func():
    global name       在函數內部,通過global關鍵字,通過局部變量修改全局變量的值
    name="czp1"
    print(name)
func()            打印局部變量中name的值
print(name)         打印全局變量中name的值
運行結果:
czp1
czp1             在運行結果中可以明顯看出,通過global,在定義局部變量的同時,也修改了全局變量的值
複製代碼


 

  global與nonlocal的區別:
  python引用變量的順序: 當前作用域局部變量->外層作用域變量->當前模塊中的全局變量->python內置變量
  global關鍵字用來在函數或局部作用域中使用全局變量,並通過glabal關鍵字在局部作用域中修改全局變量(一般不推薦這麼做)
  nonlocal關鍵字用來在函數或局部作用域使用外層(非全局)變量。

2.遞歸函數

  在一個函數的內部,可以調用其他的函數,如果某一個函數在內部調用的函數仍然是自身,這個函數就可以稱爲遞歸函數。
[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
13
複製代碼
def calc(n):
    print(n)
    if int(n/2)==0:
        return n
    return calc(int(n/2))        在calc函數中,反覆調用calc自身,這樣的函數就是遞歸函數
calc(10)
運行結果:
10
5
2
1
複製代碼


 

  注意:在遞歸函數中,並不是可以讓自身永遠的循環下去,遞歸函數中必須定義一個明確的結束條件,每進行更深一次的遞歸,解決問題的規模必須要較上一層有所減少,
  遞歸函數常用來進行二分查找。。

3.匿名函數

  匿名函數其實就是不需要指定顯示的函數。用lambda關鍵字定義,通常我們定義一個函數用這種形式:
[AppleScript] 純文本查看 複製代碼
1
2
3
4
5
def calc(x):
    return x+1
print(calc(2))
運行結果:
3

 

  而上段代碼 用匿名函數使用的話,就可以使用如下的方式,通過lambda關鍵字,傳入一個形參x,用冒號隔開,後面加入return的值。
[AppleScript] 純文本查看 複製代碼
1
2
3
4
res=lambda x:x+1
print(res(2))
運行結果:
3

 

  匿名函數單獨這麼用意義不大,但是和其他函數一起用的時候,功能就顯現的很明顯了。如下面的例子
[AppleScript] 純文本查看 複製代碼
1
2
3
4
5
6
7
8
9
複製代碼
res=map(lambda x:x**2,[2,4,6,])
for i in res:
    print(i)
運行結果:
4
16
36
複製代碼


 

  我會在接下來寫內置方法的時候具體的展示出使用匿名函數的好處。

4.高階函數

  高階函數的特點如下:1)函數接收的參數是一個函數 ;2)函數的返回值是一個函數
[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
複製代碼
將函數作爲參數傳給另一個函數
def foo(n):  
    print(n)
def bar(name):
    print("my name is %s"%name)
print(foo(bar("尼古拉斯趙四")))
運行結果:
my name is 尼古拉斯趙四
None
None                    返回兩個None,因爲在foo()和bar()函數中我沒有定義retturn。默認返回None
複製代碼


 

[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
複製代碼
將函數作爲另一個函數的返回值
def bar():
    print("from bar")
def foo():
    print("from foo")
    return bar
foo()()
運行結果:
from foo
from bar
複製代碼



4.內置函數

  首先我先介紹3個比較重要,也是比較常用的內置函數,map;reduce,filter3個內置函數

  1.map:

    將函數作用於seq中的每一個元素,並將所有的調用的結果作爲一個list返回。
    模擬一下這個需求:有一個列表[1,2,3,4],我要讓列表中的每一個元素自增1,然後打印出來,這個程序可以這樣寫:
[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
複製代碼
name=[1,2,3,4]        
res=[]                  定義一個空列表,用來接收自增一後的值
def calc(array):
    for i in array:           使用for循環,遍歷傳入列表中的每一個元素
        res.append(i+1)        
    return res
print(calc(name))
運行結果:
[2, 3, 4, 5]
複製代碼


 

  那如果 我想要的需求是讓列表自減1,自乘呢,難道要把這段代碼重複寫一段,只是改一句res.append(i-1),或者更高級一點,我們在定義一個函數:
[AppleScript] 純文本查看 複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
13
複製代碼
def increase(x):
    return x-1               定義一個自減1的函數
name=[1,2,3,4]
res=[]
def calc(func,array):           在這裏定義兩個形參,一個用來傳入函數increase,一個用來傳入列表name
    for i in array:
        res.append(increase(i))    
    return res
print(calc(increase,name))
運行結果:
[0, 1, 2, 3]
複製代碼


 

  更高級一點呢?我們用map+上面提到的匿名函數,可以很好的完成這樣的需求:
[AppleScript] 純文本查看 複製代碼
1
2
3
4
name=[1,2,3,4]
print(list(map(lambda x:x+1,name)))
運行結果:
[2,3,4,5]

 

  ok,上面寫了那麼多,兩行代碼搞定。

  2.reduce:

  reduce()函數接收的參數和 map()類似,一個函數 f,一個list,但行爲和 map()不同,reduce()傳入的函數 f 必須接收兩個參數,reduce()對list的每個元素反覆調用函數f,並返回最終結果值。可以簡單的理解爲,map接受一個列表,返回的仍然是一個列表,而reduce會進行計算,返回一個值
[AppleScript] 純文本查看 複製代碼
1
2
3
4
5
from functools import reduce                  必須導入reduce方法
name=[1,2,3,4]
print((reduce(lambda x,y:x+y,name)))      函數必須傳入兩個參數,然後傳入list
運行結果:
10

 

  reduce還有一個默認參數 ,就是可以在list後再傳入一個初始值。

 def reduce(function, sequence, initial=None)    這個初始值默認爲None

[AppleScript] 純文本查看 複製代碼
1
2
3
4
5
from functools import reduce
name=[1,2,3,4]
print((reduce(lambda x,y:x+y,name,5)))     還是上面的例子,我在最後加了初始值5(默認是none)
運行結果:
15


  3.filter

   filter讀入iterable所有的項,判斷這些項對function是否爲真,返回一個包含所有爲真的項的迭代器。如果function是None,返回非空的項。
[AppleScript] 純文本查看 複製代碼
1
2
3
4
name=["czp","cc","zp1"]
print(list(filter(lambda n:n.endswith("c"),name)))    通過匿名函數判斷條件,返回值爲真,就會打印成列表的形式
運行結果:
['cc']

{:8_507:}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章