說說 Python 函數對象的本質

Python 函數對象本質上是 function 類的實例1

1 從示例說起

def factorial(n):
    '''return n!'''
    return 1 if n < 2 else n * factorial(n - 1)


r = factorial(42)
logging.info('r -> %s', r)
logging.info('__doc__ -> %s', factorial.__doc__)
logging.info('type(factorial)  -> %s', type(factorial))

運行結果:

INFO - r -> 1405006117752879898543142606244511569936384000000000
INFO - __doc__ -> return n!
INFO - type(factorial) -> <class 'function'>

這個示例首先定義了一個計算斐波那契數列的函數,可以看到 type(factorial) 的返回值是 <class 'function'>。也就驗證了函數對象是 function 類的實例。

示例中還使用函數的 __doc__ 屬性輸出了函數定義中的註釋。這一點比 Java 強大,Java 必須把註釋定義在註解中才能通過代碼獲取到。

2 help 函數

python 中還有一個 help 函數,它可以接受一個自定義函數作爲入參,然後輸出該函數的說明文檔。形如:

help(factorial)

運行結果:

Help on function factorial in module __main__:

factorial(n)
    return n!

3 函數別名與函數傳參

函數可以賦值給變量,也可以作爲其他函數的入參。

f = factorial
logging.info('f -> %s', f)
logging.info('f(5) -> %s', f(5))

r = map(factorial, range(11))
logging.info('r -> %s', r)

r = list(map(f, range(11)))
logging.info('r -> %s', r)

運行結果:

INFO - f -> <function factorial at 0x0000027278917798>
INFO - f(5) -> 120
INFO - r -> <map object at 0x000002727893F588>
INFO - r -> [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

示例中首先把之前定義的斐波那契數列函數賦值給變量 f;可以看到這個變量本身就是 factorial 函數的引用。還可以像使用 factorial 函數一樣,直接給 f 函數傳參,計算出想要的斐波那契數列結果。

接着把 factorial 函數傳入 Python 的 map() 函數。map() 函數的語法爲:map(function, iterable, ...),它會以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表2

因爲在 Pyhon 3.x 中 map() 函數只返回迭代器,所以示例中對其進行 list 轉換。這樣就輸出了從 0 到 11 作爲入參的各自斐波那契結果列表。因爲 range() 函數的語法爲:range(start, stop[, step]),默認從 0 開始3,所以範圍是從 0 到 11。


函數與整數、字符串與字典一樣,它們都是 Python 世界中的一等公民。


參考資料:
【1】Luciano Ramalho (作者),安道,吳珂 (譯者).流暢的Python[M].人民郵電出版社,2017:239-240.
【2】Python map() 函數.
【3】Python range() 函數用法.

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