1. 程式人生 > >15.python函數語言程式設計(二)—返回函式,匿名函式

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。外函式則儲存了該內函式的地址。在我理解看來,定義函式的過程,其實就是為某一段語句(函式體)指定一段記憶體地址(函式名)存放的過程。

這個過程最終完成後,生成了一個記憶體地址(函式名)。這就解釋了程式,為什麼會列印一個16進位制數,這個數是sum函式的地址。這裡再為資料結構鼓掌!(呱唧。。呱唧。。)既然內函式生成了一個地址,那麼對於外函式來說,當然是返回該地址了。

對於上面的程式來說,由於內函式每次執行的時候都會為函式名新分配一個記憶體地址。所以兩次返回的地址是不同的。這就解釋了,為什麼兩次返回地址不一樣。而第一個程式,只分配了一個地址,所以列印的地址一樣。

你可能想問了。那怎麼得到結果呢?

地址都有了,只要執行就可以了啦!

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。

有一點注意的地方是,只能有一個表示式。可以將匿名函式賦給一個變數,然後使用。也可以返回匿名函式。

其實我感覺匿名函式這個東西,沒什麼用。有點華而不實。看起來這個函式的功能是為了防止函式名衝突,或者是一定程度上方便程式設計師。因為他不用再定義一個函式。但我想,一個有著良好程式設計習慣的程式設計師,是不怕這個麻煩的。所以就不多說了。