Python的閉包函數


 閉包函數

  基於函數對象的概念,可以將函數返回到任意位置去調用 ,但是作用域的關系是在定義完函數時就已經被確定了的,與函數的調用位置無關。

一、學習閉包函數的必備知識點:
閉包函數=名稱空間與作用域+函數嵌套+函數對象
核心點:名字的查找關系是以函數定義階段為准
二、什么是閉包函數?
閉:封閉關閉,封閉的函數。指的是該函數是內嵌函數,也就是說被麻袋裝起來了
# 封閉的函數實例: # def f1(): # 這里的f1就是麻袋 # def f2(): # 這里的f2就是閉函數 # pass
    包:包住,在閉的基礎上,指的是該函數f2包含對外層函數f1作用域名字的引用。(不是對全局作用域)
# 閉包函數實例1: # def f1(): # 這里的f1就是麻袋 # x = 1 # def f2(): # 這里的f2就是閉函數 # print(x) # 這里的x引用到了外層函數,所以此時的f2就是閉包函數 # f2() # x = 222 # f1() # 1

# 閉包函數實例2:閉包函數之名稱空間與作用域+函數嵌套的應用 # def f1(): # 這里的f1就是麻袋 # x = 333333333333333333333 # def f2(): # 這里的f2就是閉函數 # print(x) # 這里的x引用到了外層函數,所以此時的f2就是閉包函數 # f2() # x = 222 # def foo(): # x = 444 # f1() # # foo() # 333333333333333333333

# 閉包函數實例3: # def f1(): # 這里的f1就是麻袋 # x = 333333333333333333333 # def f2(): # 這里的f2就是閉函數 # print(x) # 這里的x引用到了外層函數,所以此時的f2就是閉包函數 # f2() # x = 111 # def bar(): # x = 4444 # f1() # def foo(): # x = 2222 # bar() # # foo() # 333333333333333333333

# 閉包函數實例4:閉包函數之函數對象 # 思路:只要我拿到f2的內存地址,那么無論我到哪里調用都可以用到。 # 我想要在全局作用域拿到f2的內存地址。f2就可以在任意的地方調用了。
def f1(): x = 333333333333333333333
    def f2(): print("函數f2的x:",x) # print(f2) # 打印f2的內存地址
    return f2  # 這里注意不要加(),不加()拿到了內存地址 # 這里的f是全局變量,但是f的值來自局部,打破了層級上的限制。 
f = f1() # print(f) # 這里我可以獲得到f2的內存地址,<function f1.<locals>.f2 at 0x0000025CC8499670>

# 拿到了f2的內存地址后加括號執行得到結果 # f() # 運行結果:函數f2的x: 333333333333333333333

def foo(): x = 555 f() foo() # 函數f2的x: 333333333333333333333

三、閉包函數的應用場景?(為什么要有閉包函數?)
# 四、兩種為函數體傳參的方式 # 1、方式一:直接把函數體需要的參數定義成形參,直接傳參 # def f2(x): # print(x) # f2(1) # f2(2) # f2(3)

# 2、方式二:使用閉包函數 # def f1(): # 包的效果 # x = 3 # def f2(): # print(x) # return f2 # 返回f2的內存地址,把f2內存地址放到全局 # # f = f1() # print(f) # 獲得到了f2的內存地址:<function f1.<locals>.f2 at 0x0000013A25559670> # f() # 3

# 把上面的函數寫活,修改函數體的參數
def f1(x):  # 包的效果
    # x = 3 # 這樣就寫死了,如何寫活?
    def f2(): print(x) return f2  # 返回f2的內存地址,把f2內存地址放到全局
 f = f1(3) print(f)  # 獲得到了f2的內存地址:<function f1.<locals>.f2 at 0x0000013A25559670>
f()  # 3
# 爬取三個網址的信息 # import requests # response = requests.get("https://www.baidu.com") # print(response.text) # requests.get("https://www.cnblogs.com/liunaixu/") # print(response.text) # requests.get("https://www.cnblogs.com/linhaifeng/") # print(response.text)

# 優化上面代碼:寫一個下載的功能, # 傳參的方案一: # import requests # def get(url): # # response = requests.get("https://www.baidu.com") # # print(response.text) # response = requests.get(url) # print(len(response.text)) # get("https://www.baidu.com") # get("https://www.cnblogs.com/liunaixu/") # get("https://www.cnblogs.com/linhaifeng/")

# 使用閉包函數:方案二
import requests def outter(url): # url='https://www.baidu.com' # 不能寫死
    def get(): response = requests.get(url) print(len(response.text)) return get baidu = outter('https://www.baidu.com')   # 拿到outter的內存地址
baidu() bokeyuan = outter('https://www.cnblogs.com/liunaixu/') bokeyuan()

 

# 四、驗證closures()函數
x = 1
def outer(): x = 2
    def inner(): print(x) return inner func = outer() func() # 2 # 可以通過函數的closure屬性,查看到閉包函數所包裹的外部變量
print(func.__closure__) # (<cell at 0x000002A01FB86B80: int object at 0x00007FFADB77D6C0>,)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM