15.python函數語言程式設計(二)—返回函式,匿名函式
1)返回函式
(1)返回函式地址
高階函式除了可以接收函式作為輸入以外,還可以輸出函式。示例程式碼如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def func(*arg):
def sum():
he=0
for n in arg:
he=n+arg
return he return sumprint func([1,2,3,4])print func([1,2,3,4])
輸出結果為下:
<function sum at 0x023F3A70> <function sum at 0x023F3A70>
這輸出的是什麼鬼???手動黑人問號。
然後我們這裡改一下:
f1=func([1,2,3,4])
f2=func([1,2,3,4])
print f1
print f2
則輸出結果變為:
<function sum at 0x02333A70>
<function sum at 0x023339F0>
這是怎麼回事??這又是什麼鬼!
這裡我們求一個可變引數的值。我們先定義了外函式func,設定可變引數*arg為形參。再定義了內函式sum()。這時,內函式儲存,或者說是引用了外函式的引數值*arg。然後返回結果he。外函式則儲存了該內函式的地址。在我理解看來,定義函式的過程,其實就是為某一段語句(函式體)指定一段記憶體地址(函式名)存放的過程。
對於上面的程式來說,由於內函式每次執行的時候都會為函式名新分配一個記憶體地址。所以兩次返回的地址是不同的。這就解釋了,為什麼兩次返回地址不一樣。而第一個程式,只分配了一個地址,所以列印的地址一樣。
你可能想問了。那怎麼得到結果呢?
地址都有了,只要執行就可以了啦!
f=func(1,2,3,4)
print f()
輸出:10
在這之前,我犯了一個錯誤:
he=n+he
我寫成了
he=n+arg
結果,報錯”TypeError: unsupported operand type(s) for +: 'int' and 'tuple'“,一定要細心啊。
(2)閉包
首先來看一下什麼是閉包,當內函式引用了外函式的臨時變數,而且返回後,下次函式繼續引用內函式的區域性變數,這就形成了一個閉包。
這裡要注意的是:返回的函式沒有立即執行,直到呼叫了f(),才執行。
另外,在內函式中,不要使用區域性迴圈變數i。我們看一個例子:來源於廖雪峰
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def func():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3=func()
list=[f1,f2,f3]
print list
但是很遺憾,我沒有成功,輸出列印後,是這樣的:
[<function f at 0x025B3A70>, <function f at 0x025B39F0>, <function f at 0x025B3AF0>]
從字面上看是我把各個列表元素的地址打印出來了。也就是說我們需要,找到地址所對應的值,因此我試著用*符號來指向值,但是提示:invalid syntax。這個問題先留著,回頭再看。
2)匿名函式
什麼是匿名函式呢?就是不需要起名字的函式。示例程式碼如下:
map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
實際上就是:
def f(x):
return x * x
lambda是匿名函式的關鍵字,定義引數x,返回x*x。
有一點注意的地方是,只能有一個表示式。可以將匿名函式賦給一個變數,然後使用。也可以返回匿名函式。
其實我感覺匿名函式這個東西,沒什麼用。有點華而不實。看起來這個函式的功能是為了防止函式名衝突,或者是一定程度上方便程式設計師。因為他不用再定義一個函式。但我想,一個有著良好程式設計習慣的程式設計師,是不怕這個麻煩的。所以就不多說了。