return編程python_python3 第二十一章 - 函數式編程之return函數和閉包

我們來實現一個可變參數的求和。通常情況下,求和的函數是這樣定義的:

def calc_sum(*args):

ax=0for n inargs:

ax= ax +nreturn ax

但是,如果不需要立刻求和,而是在后面的代碼中,根據需要再計算怎么辦?可以不返回求和的結果,而是返回求和的函數:

def lazy_sum(*args):defsum():

ax=0for n inargs:

ax= ax +nreturnaxreturnsum

f= lazy_sum(1, 2, 3, 4)print(f)print(f())

以上代碼,輸出:

.sum at 0x1014476a8>

10

當我們調用lazy_sum()時,返回的并不是求和結果,而是求和函數,調用函數f時,才真正計算求和的結果。

在這個例子中,我們在函數lazy_sum中又定義了函數sum,并且,內部函數sum可以引用外部函數lazy_sum的參數和局部變量,當lazy_sum返回函數sum時,相關參數和變量都保存在返回的函數中,這種稱為“閉包(Closure)”的程序結構擁有極大的威力。

請再注意一點,當我們調用lazy_sum()時,每次調用都會返回一個新的函數,即使傳入相同的參數:

def lazy_sum(*args):defsum():

ax=0for n inargs:

ax= ax +nreturnaxreturnsum

f1= lazy_sum(1, 2, 3, 4)

f2= lazy_sum(1, 2, 3, 4)print('f1==f2 :', f1 == f2)

以上代碼,輸出:

f1==f2 : False

f1()和f2()的調用結果互不影響。

閉包(closure)是函數式編程的重要的語法結構。下面看一個閉包的實際例子:

defline_conf(a, b):defline(x):return a * x +breturnline

line1= line_conf(1, 2)

line2= line_conf(3, 7)print(line1(5), line2(5))

這個例子中,函數line與環境變量a,b構成閉包。在創建閉包的時候,我們通過line_conf的參數a,b說明了這兩個環境變量的取值,這樣,我們就確定了函數的最終形式(y = x + 2和y = 3x + 7)。我們只需要變換參數a,b,就可以獲得不同的直線表達函數。由此,我們可以看到,閉包也具有提高代碼可復用性的作用。

如果沒有閉包,我們需要每次創建直線函數的時候同時說明a,b,x。這樣,我們就需要更多的參數傳遞,也減少了代碼的可移植性。利用閉包,我們實際上創建了泛函。line函數定義一種廣泛意義的函數。這個函數的一些方面已經確定(必須是直線),但另一些方面(比如a和b參數待定)。隨后,我們根據line_conf傳遞來的參數,通過閉包的形式,將最終函數確定下來。

閉包與并行運算

閉包有效的減少了函數所需定義的參數數目。這對于并行運算來說有重要的意義。在并行運算的環境下,我們可以讓每臺電腦負責一個函數,然后將一臺電腦的輸出和下一臺電腦的輸入串聯起來。最終,我們像流 水線一樣工作,從串聯的電腦集群一端輸入數據,從另一端輸出數據。這樣的情境最適合只有一個參數輸入的函數。閉包就可以實現這一目的。這也是函數式編程又熱起來的一個重要原因。函數式編程早在1950年代就已經存在,但應用并不廣泛。然而,我們上面描述的流水線式的工作并行集群過程,正適合函數式編程。由于函數式編程這一天然優勢,越來越多的語言也開始加入對函數式編程范式的支持。

需要注意的問題是,返回的函數并沒有立刻執行,而是直到調用了f()才執行。我們來看一個例子:

defcount():

fs=[]for i in range(1, 4):deff():return i*i

fs.append(f)returnfs

f1, f2, f3=count()print('f1():', f1())print('f2():', f2())print('f3():', f3())

在上面的例子中,每次循環,都創建了一個新的函數,然后,把創建的3個函數都返回了。

你可能認為調用f1(),f2()和f3()結果應該是1,4,9,但實際結果是:

f1(): 9f2():9f3():9

全部都是9,原因就在于返回的函數引用了變量i,但它并非立刻執行。等到3個函數都返回時,它們所引用的變量i已經變成了3,因此最終結果為9。

返回函數不要引用任何循環變量,或者后續會發生變化的變量。如果一定要引用循環變量怎么辦?方法是再創建一個函數,用該函數的參數綁定循環變量當前的值,無論該循環變量后續如何更改,已綁定到函數參數的值不變:

defcount():deff(j):defg():return j *jreturng

fs=[]for i in range(1, 4):

fs.append(f(i))#f(i)立刻被執行,因此i的當前值被傳入f()

returnfs

f1, f2, f3=count()print('f1():', f1())print('f2():', f2())print('f3():', f3())

以上代碼,輸出:

f1(): 1f2():4f3():9

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378835.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378835.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378835.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

黑色背景下,計算照片白色的區域面積和周長

黑色背景下,計算照片白色的區域面積和周長 import cv2 img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/beyond.png,1)#第一個參數為選擇照片的路徑,注意照片路徑最后一個為正斜杠其他都為反斜杠;第二個參數,其中1表示所選照…

php連接mssql數據庫的幾種方式

數據庫查詢不外乎4個步驟,1、建立連接。2、輸入查詢代碼。3、建立查詢并取出數據。4、關閉連接。 php連接mssql數據庫有幾個注意事項,尤其mssql的多個版本、32位、64位都有區別。 首先,php.ini文件中;extensionphp_pdo_mssql.dll ;extensionp…

通俗易懂:快速理解P2P技術中的NAT穿透原理

目錄1、基礎知識1.1、什么是NAT?1.2、為什么會有NAT?1.3、NAT有什么優缺點?2、NAT的實現方式2.1、靜態NAT2.2、NAPT3、NAT的主要類型3.1、完全錐型NAT(Full Cone NAT,后面簡稱FC)3.2、受限錐型NAT&#xff…

duration java_Java Duration類| toNanos()方法與示例

duration javaDuration Class toNanos()方法 (Duration Class toNanos() method) toNanos() method is available in java.time package. toNanos()方法在java.time包中可用。 toNanos() method is used to convert this Duration into the number of nanoseconds. toNanos()方…

java 負載均衡_java負載均衡 - 歲月靜好I的個人空間 - OSCHINA - 中文開源技術交流社區...

作用對系統的高可用,網絡壓力的緩解,處理能力擴容的重要手段之一。服務器負載我們通常所說的負載是指:服務器負載軟硬件負載服務器負載又分為:軟件負載--硬件負載軟件負載:通過在服務器上安裝一些具有負載功能或模塊的…

b tree和b+tree_B TREE實施

b tree和btreeB TREE及其操作簡介 (Introduction to B TREE and its operations) A B tree is designed to store sorted data and allows search, insertion and deletion operation to be performed in logarithmic time. As In multiway search tree, there are so many nod…

黑色背景下,將照片內封閉空心圖案的空心區域染成Cyan并保存

在黑色背景下,將照片內封閉空心圖案的空心區域染色 import cv2 import numpy as np img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/beyond.png,1)#第一個參數為選擇照片的路徑,注意照片路徑最后一個為正斜杠其他都為反斜杠;第二個參數…

Ubuntu輸入su提示認證失敗的解決方法

Ubuntu輸入su提示認證失敗的解決方法 啟動ubuntu服務時竟然提示權限不夠,用su切換,輸入密碼提示認證失敗,這下搞了吧,后來一經查閱原來Ubuntu安裝后,root用戶默認是被鎖定了的,不允許登錄,也不允…

SDP協議基本分析(RTSP、WebRTC使用)

目錄一、介紹二、標準 SDP 規范1. SDP 的格式2. SDP 的結構(1)會話描述(2)媒體描述三、WebRTC 中的 SDP一、介紹 SDP(Session Description Protocal)以文本描述各端(PC 端、Mac 端、Android 端…

MFC六大關鍵技術(第四部分)——永久保存(串行化)

MFC 六大關鍵技術 ( 第四部分 ) ——永久保存(串行化) 先用一句話來說明永久保存的重要:弄懂它以后,你就越來越像個程序員了! 如果我們的程序不需要永久保存,那幾乎可以肯定是一個小玩兒。那怕我們的記事本…

在網絡中配置思科交換機

By default, all ports of a switch are enabled. As we are talking about layer 2 switching, there is no need to configure IP address or any routing protocol on the switch. In such a situation, the configuration is not focused on the switch. 缺省情況下&#…

黑色背景下,描繪照片的輪廓形狀并保存

描繪照片的輪廓形狀并保存 import cv2 from matplotlib import pyplot as plt # 1.先找到輪廓 img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/beyond.png, 0) _, thresh cv2.threshold(img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) image, conturs, hierarchy c…

java pdf合并_Java 合并、拆分PDF文檔

本文將介紹如何在Java程序中合并及拆分PDF文檔,合并文檔時,包括合并多個不同PDF文檔為一個文檔,以及合并PDF文檔的不同頁面為一頁;拆分文檔是,包括將PDF文檔按每一頁拆分,以及按指定頁數范圍來拆分。下面將…

HDU4405 期望

對于期望,首先,對于這個公式中p表示概率,x表示隨機變量 展開則為 ex p1*x1p2*x2p3*x3....... 對于本題 假設 ex[ i ]表示當前 i 走到 n 的期望值。所以若 i 處沒有飛機,ex[ i ]sigma(1/6*ex[ik])1 其中(k1...6) (1表示…

調用本地電腦攝像頭并進行按P進行捕獲照片并保存,按下Q退出

調用本地電腦攝像頭并進行按P進行捕獲照片并保存,按下Q退出 灰度攝像頭顯示: import cv2 cap cv2.VideoCapture(0) if not cap.isOpened():print("Cannot open camera")exit() while True:# 逐幀捕獲ret, frame cap.read()# 如果正確讀取幀…

intersect函數_PHP array_intersect()函數與示例

intersect函數PHP array_intersect()函數 (PHP array_intersect() Function ) array_intersect() function is used to find the matched elements from two or more elements. Function “array_intersect()” compares the values of the first array with the other arrays …

很全的SQL注入語句

1、返回的是連接的數據庫名and db_name()>02、作用是獲取連接用戶名and user>03、將數據庫備份到Web目錄下面;backup database 數據庫名 to diskc:\inetpub\wwwroot\1.db;--4、顯示SQL系統版本and 1(select VERSION) 或and 1convert(int,version)--5、判斷xp_cmdshell擴展…

使用DataTable更新數據庫

1、修改數據 DataRow dr hRDataSet.Tables["emp"].Rows.Find(textBox3.Text);//DataRow dr hRDataSet.Tables["emp"].Select("id"textBox3.Text)[0];dr.BeginEdit();dr["name"] textBox1.Text;dr.EndEdit();SqlCommandBuilder cmdn…

java異常體系_JAVA異常體系結構詳解

一、什么是異常異常:程序在運行過程中發生由于硬件設備問題、軟件設計錯誤等導致的程序異常事件。(在Java等面向對象的編程語言中)異常本身是一個對象,產生異常就是產生了一個異常對象。 ——百度百科二、異常體系Java把異常當作對象來處理&#xf…

對照片質量進行壓縮

對照片質量進行壓縮 其實無論是jpg還是png都是已經壓縮編碼化的格式罷了,原圖片的大小要遠遠大于壓縮編碼后的格式 1,像素:圖片放大到一定程度之后的一個個的小方塊 2,RGB:每一個像素(小方塊)都…