亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

函數里面包含函數

函數里面包含函數

假慕粉9527 2016-06-23 21:07:52
def make_adder(addend):? ? def adder(augend):? ? ? ? return augend + addend? ? return adderp = make_adder(23)print make_adder(23)print pprint p(100)最后的三個print到底有什么關系?有些直接得出答案,有些得到的是地址;print p是不是等于print make_adder(23)
查看完整描述

2 回答

已采納
?
清波

TA貢獻165條經驗 獲得超90個贊

>>>?len(range(2))
2
>>>?a=len
>>>?a(range(2))
2

每次看到別人問關于 函數傳遞,調用,返回等問題時,我就很開心,哈哈。 因為我也是從這里開始出發,迷上函數式編程的。感覺它比 OOP 更加抽象,也更加有意思。


好了不廢話了, 開始解題。 首先說上面的代碼: 第三行, 我們把len函數 賦值給了一個變量a, 接著在第四行,就可以調用函數a 了。 這說明函數本身和 Python 的其他對象一樣(如,數字 1,2;字符串:'aa' 等)是可以作為值去賦值給其他變量名的, 同時 函數也可以作為 另一個函數的返回值

def?make_adder(addend):
????def?adder(augend):
????????return?augend?+?addend
????return?adder
????
p?=?make_adder(23)

print?(make_adder(23))????????????????????#(1)
print?(p)?????????????????????????????????#(2)
print?(p(100))????????????????????????????#(3)
print?(p.__closure__)?????????????????????#(4)
print?(p.__closure__[0].cell_contents)????#(5)

##下面是這5次?輸出,?請自動修正我用的?Python3.x?print()?語法
#(1)?<function?make_adder.<locals>.adder?at?0x0000019AE2F2E950>
#(2)?<function?make_adder.<locals>.adder?at?0x0000019AE2F2E8C8>
#(3)?123
#(4)?(<cell?at?0x0000019AE2BA8C18:?int?object?at?0x000000006767F1F0>,)
#(5)?23

好, 我們依次解釋這五次輸出,順便講下 幾乎所有支持函數式編程的語言 都會有的概念: 閉包。這大概也是面試官最愿意問的問題吧:順嘴一提,面試者隨便一說,面試官點點頭,能最大程度緩解氣氛 是不? 哈哈, 反正我做面試的時候會問。

  1. 因為, make_adder 這個函數的返回值 是一個函數, 并且調用這個函數時,必須傳遞一個參數(后面這個參數的值,就成為了p 的閉包中很重要的組成部分)。所以第一個print 很好理解,就是一個函數體(把在函數中定義的函數 adder作為值 返回了)。

  2. 這第二個print 就和開篇的例子一個道理,講一個函數作為值賦值給一個變量名了, 那么變量p 也是一個函數體。

  3. 至于第三個,就是對于函數p 的調用, 自然 打印的就是這個函數執行的結果,或者說是返回的結果。

  4. 好,從這里開始就是閉包了,閉包 和 詞法作用域(lexical scoping)的概念,復制過來也就是幾句簡單但是不怎么容易理解的話, 這里就不贅述了,想了解請用搜索引擎。簡單來說就是,當一個函數被定義時,它擁有的不僅僅是定義時的那些邏輯代碼 還 擁有當時(定義時)的變量環境。 Python作為一個以優美著稱的語言,必須 可以拿出解釋這個概念的直觀方法, 那就是每個函數 都有一個 閉包屬性, 這第四次print 就是打印出了 函數的這個屬性, 它是一個元組,其元素是 cell 類型。

  5. 第五次 print ,就很簡單了, 就是打印出了, 函數的 閉包(tuple) 的第一個元素(cell)的內容(cell_contents)。


說了這么多, 也不知道題主理解了沒有??偟膩碚f, 正是由于 函數擁有閉包的這屬性, 才能在 其定義的外部調用時, 不會忘記 或者找不到 其應該 附帶的一些變量(此例中的 23)。


如果將函數改成:

def?make_adder(addend):
????a?=?100
????def?adder(augend):
????????return?augend?+?addend?+?a
????return?adder

五次輸出有什么不同呢? 請自行實驗,對比,領悟 Python 中 函數的閉包屬性。

查看完整回答
1 反對 回復 2016-06-24
?
Jenkins_lee

TA貢獻12條經驗 獲得超18個贊

1、return adder ,輸出adder的內存地址

2、p = return adder , 同樣是輸出adder的內存地址

3、print make_adder(23)(100),調用adder函數返回23+100的值,這里23取的是make_adder函數的參數值,100是adder函數的參數值

查看完整回答
3 反對 回復 2016-06-24
  • 2 回答
  • 0 關注
  • 1930 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號