**函數作為返回值**
在高階函數那一講,我們已經知道了,高階函數可以接受函數作為參數,其實函數也可以作為結果值返回。
在函數嵌套那一講我們講了這么一個例子
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myAdd(a,b):
'''兩數求和悄悄加一'''
sum = a + b
def innerAdd(num):
return num + 1
sum = innerAdd(sum)
return sum
print(myAdd(1,2))
~~~
我們直接把兩數求和再加一的結果返回了,如果不需要立刻知道結果,而是在后面的代碼中,根據需要再計算怎么辦?所以就不能直接返回結果了,而是返回計算的函數。
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myAdd(a,b):
'''兩數求和悄悄加一'''
sum = a + b
def innerAdd():
return sum + 1
return innerAdd
f = myAdd(1,2)
#第一次打印
print(f)
#第二次打印
print(f())
#第三次打印
print(myAdd(1,2) == myAdd(1,2))
~~~
運行結果
~~~
airvip@airvip$ ./test.py
#第一次打印結果
<function myAdd.<locals>.innerAdd at 0x7f5b2a1ac6a8>
#第二次打印結果
4
#第三次打印結果
False
~~~
當我們調用 myAdd() 時,返回的并不是最終的結果,而是一個函數,再調用函數 f 時,才真正計算得到結果。
需要特別注意第三次打印的結果為 False 假。
在這個例子中,我們在函數 myAdd 中又定義了函數 innerAdd,內部函數 innerAdd 可以使用用外部函數 myAdd 的參數和局部變量,當 myAdd 返回 innerAdd 函數時,其調用的參數和變量都已經保存在返回的函數中,這種方式稱為“閉包(Closure)”。
另外當一個函數返回了一個函數后,其內部的局部變量還被新函數使用中,返回的函數并沒有立刻執行,只有調用了之后才執行,我們來看下面這個例子。
~~~
>>> def myAdd(a,b):
... Fl = []
... sum = a+b
... for i in range(2):
... def innerAdd():
... return sum + i
... Fl.append(innerAdd)
... return Fl
~~~
在程序中每次循環都創建了一個新的函數,最后一起把創建的函數都返回了
調用,我們想要的結果是 3,4 ,然而真實結果卻是:
~~~
>>> f1,f2 = myAdd(1,2)
>>> f1()
4
>>> f2()
4
~~~
結果全為 4 ,這是為什么呢?因為返回的函數引用了變量 i,它并沒有立刻執行。等到所有函數都返回時,它們使用的變量 i 已經都變成了 1,所以結果就都是 4 了。
那如何解決呢?想辦法將傳入函數的參數綁定在函數上無法修改,這就需要再創建一個函數。
~~~
>>> def myAdd(a,b):
... Fl = [];
... sum = a+b
... def center(i):
... def innerAdd():
... return sum + i
... return innerAdd
... for i in range(2):
... Fl.append(center(i))
... return Fl
...
~~~
再次調用
~~~
>>> f1,f2 = myAdd(1,2)
>>> f1()
3
>>> f2()
4
~~~
總結:
每次調用以函數作為返回值的函數時,即便傳遞的參數一模一樣,返回的結果也不同。
在編寫返回函數時,一定不要使用任何后續操作會發生變化的變量。
- 跟老司機學Python
- 了解Python
- 1、python簡介
- 2、Python發展史
- 3、Python特點
- 4、Python解釋器
- 入坑Python
- 1、Python環境搭建
- 2、設置環境變量
- 3、開始使用Python
- 4、運行Python程序
- 掌握Python基礎
- Python基礎知識
- Python運算符
- 算術運算符
- 比較運算符
- 賦值運算符
- 邏輯運算符
- 位運算符
- 成員運算符
- 身份運算符
- 運算符優先級
- Python的變量與常量
- Python數據類型
- Number數值
- String字符串
- List列表
- Tuple元組
- Dictionary字典
- Set集合
- Python流程控制語句
- 條件判斷
- 循環控制
- Python函數
- 1、函數是什么
- 2、函數的定義
- 3、函數的參數
- 4、函數的調用
- 5、嵌套函數
- 6、遞歸函數
- 7、匿名函數
- 8、函數式編程
- 9、高階函數
- 1、map
- 2、reduce
- 3、filter
- 4、sorted
- 10、返回函數
- 11、偏函數
- Python文件IO操作
- 標準輸入輸出
- 讀寫文件
- with讀寫文件
- Python高級特性
- 1、列表生成式
- 2、迭代器
- 3、生成器
- 4、裝飾器
- Python模塊初探
- 1、模塊與包
- 2、創建模塊
- 3、模塊中的作用域
- 4、模塊的導入
- Python面向對象編程
- 類與對象
- 類的定義及使用
- 面向對象特性
- 類中的訪問域
- 查看對象詳情
- Python面向對象進階
- 類中的方法
- 類中的特殊成員
- 限制對象的屬性
- 再聊多繼承
- 裝x式創建類
- 創建元類
- Python內置模塊
- os模塊
- sys模塊
- random模塊
- time模塊
- datetime模塊
- shutil模塊
- collections模塊
- base64模塊
- json模塊
- hashlib模塊
- xml模塊
- 1. SAX解析XML
- 2. DOM解析XML
- 3. ElementTree解析XML
- urllib模塊
- logging模塊
- re模塊
- Python第三方模塊
- Pillow與PIL
- Requests
- Tablib
- Xpinyin
- Chardet
- Pycurl
- Virtualenv
- Python操作數據庫
- Mysql操作
- Sqllite操作
- Mongodb操作
- Redis操作
- Python的GUI編程
- Python中GUI的選擇
- Tkinter
- wxPython
- Socket網絡編程
- Socket網絡編程簡聊
- Socket內建方法
- TCP協議編程
- UDP協議編程
- TCP與UDP
- Python電子郵件
- SMTP發郵件
- POP3收郵件
- IMAP收郵件
- 進程線程
- 進程與線程
- 進程編程
- 使用進程池
- 進程間的通信
- 線程編程
- 使用線程鎖
- Python的GIL
- Web編程
- WSGI介紹
- Web框架
- Flask使用
- 模板jinjia2使用
- 項目結構規劃
- 異步與協程
- 概念掃盲
- 異步IO進化之路
- 協程是什么
- yield協程編程
- yield from
- asyncio
- async與await
- aiohttp之client
- aiphttp之server
- 網絡爬蟲
- 網絡爬蟲簡聊
- Beautiful Soup模塊的使用
- pyquery 模塊的使用
- selenium模塊的使用
- 爬取段子實例
- 錯誤與調試
- 錯誤
- 錯誤處理
- 拋出錯誤
- 高效的調試
- Python重要語句
- pass語句
- return語句
- Python開發必知
- pip使用詳解
- 如何對列表進行迭代
- 如何對字典進行迭代
- 字符串格式化
- 知識擴展
- 網絡模型
- GUI是什么