回複內容:
題主可能並沒有理解
“在Python中,函數本身也是對象”
這一本質。那不妨慢慢來,從最基本的概念開始,討論一下這個問題:
1. Python中一切皆對象
這恐怕是學習Python最有用的一句話。想必你已經知道Python中的list, tuple, dict等內建資料結構,當你執行:
alist = [1, 2, 3]
題主遇到的這個問題很典型,就是把修飾器當成了封裝器, 認為調用 useful 前先調用 addspam。其實 useful 不是被 addspam 封裝了,而是替換了。調用 useful 調用的就是 new。餘下的 fn 指向原來的 useful, 才需要第一類函數、範圍繼承等知識點來理解。可變參數 *args 則是幹擾的另外一個知識點,替換成 x, y 就行了。Python裡面的@只是一個syntax sugar而已,在你聲明useful的時候,interpreter檢查到你有外面有裝飾器@addspam的存在,這時候你就可以大致理解成解譯器做了以下的手腳:
useful = addspam(useful)
很好的問題!
請搜尋higher order functions瞭解更多資訊。
因為我沒有能力來清楚地解釋,就放幾篇我在學習函數式編程的時候看到的比較好的博文來協助你理解。
函數式編程 | 酷 殼
Python修飾器的函數式編程
1.6 Higher-Order Functions
6. Functional Programming
我喜歡最後一篇文章,通過執行個體來理解效果更好。Python中,函數並沒有什麼特殊的,就是一個對象。你沒理解修飾器。
用addspam修飾了useful後,你應該理解為這個函數變成了new。
當調用useful函數的時候,其實是調用了new。沒有複製,函數也是個對象,基本就和你 return 一個 list 一個 dict 沒什麼兩樣。
試試看在 Python REPL 中建立一個 function:
>>> def foobar(): print("你好")>>> foobar>>> func_list = [foobar, foobar, foobar]>>> func_list[0]()
不是簡單地返回函數。至少在Python裡,def定義的函數和lambda定義的函數,後者是包含closure的。
具體closure是什麼,這真不是一句話能說清,我也不覺得我能說好,所以還是自己搜一下吧。
不要說我歧視用百度查這種問題,這去Google搜個nested functions多好。