python閉包的例項詳解

2022-09-24 23:21:11 字數 2954 閱讀 5774

1、在外部函式中定義內部函式,內部函式包含訪問外部函式。即使外部函式的生命週期結束後,內部函式仍然可以訪問外部函式變數。

2、外部函式的返回值是內部函式本身。

def outer():

cheer = 'hello '

def inner(name):

return cheer + name

return inner

if __name__ == "__main__":

#輸出hello kevin

print(outer()('kevin'))

知識點擴充套件:

閉包的概念

我們嘗試從概念上去理解一下閉包。

在一些語言中,在函式中可以(巢狀)定義另乙個函式時,如果內部函式引用了外部函式的變數,則可能產生閉包。閉包可以用來在乙個函式與一組「私有」變數之間建立關聯關係。在給定函式被多次呼叫過程中,這些私有變數能夠保持永續性。

用比較容易懂得人話說,就是當某個函式被當成物件返回時,夾帶了外部變數,就形成了乙個閉包。看下例子:

def make_printer(msg):

def printer():

print(msg) # 夾帶私貨(外部變數)

return printer # 返回的是函式,帶私貨的函式

printer = make_printer("foo!")

printer()

支援將函式當成物件使用的程式語言,一般都支援閉包。比如python,j**ascript。

如何理解閉包

閉包存在有什麼意義呢?為什麼需要閉包

我個人認為,閉包存在的意義就是它夾帶了外部變數(私貨),如果它不夾帶私貨,它和普通的函式就沒有任何區別。同乙個的函式夾帶了不同的私貨,就實現了不同的功能。其實你也可以這麼理解,閉包和面向介面程式設計的概念很像,可以把閉包理解成輕量級的介面程式設計。

介面定義了一套對方法簽名的約束法則。

def tag(tovhxfoag_name):

def add_tag(content):

return ">".format(tag_name, content)

return add_tag

content = "hello"

add_tag = tag('a')

print(add_tag(content)) # hello

add_tag = tag('b')

print(add_tag(content)) # hello

在這個例子裡,我們想要給content加tag功能,但是具體的tag_name是什麼樣子的要根據實際需求來定,對外部呼叫的介面已經確定,就是add_tag(content)。如果按照面向介面方式實現,我們會先把add_tag寫成介面,指定其函式和返回型別,然後分別去實現a和b的add_tag。

但是在閉包的概念中,add_tag就是乙個函式,它需要tag_name和content兩個引數,只不過tag_name這個引數是打包帶程式設計客棧走的。所以一開始時就可以告訴我怎麼打包,然後帶走就行。

上面的例子不太生動,其實我們生活和工作中,閉包的概念也很常見。比如說手機撥號,你只關心**打給誰,而不會去糾結每個 品牌的手機是怎麼實現的,用到了哪些模組。再比如去餐館吃飯,你只要付錢就可以享受到服務,你並不知www.cppcns.com道那桌飯菜用了多少地溝油。這些都可以看成閉包,返回來的是一些功能或服務(打**,用餐),但是這些功能使用了外部變數(天線,地溝油等等)

你也可以把乙個類例項看成閉包,當你在構造這個類時,使用了不同的引數,這些引數就是閉包裡的包,這個類對外提供的方法就是閉包的功能。但是類遠遠大於閉包,因為閉包只是 乙個可以執行的函式,但是類例項則有可能提供很多方法。

何時使用閉包

其實閉包在python中很常見,只不過你沒特別注意這就是乙個閉包。比如python中的裝飾器decorator,假如你需要寫乙個帶引數的裝飾器,那麼一般都會生成閉包。

為什麼?因為python的裝飾器是乙個固定的函式介面形式。它要求你的裝飾器函式(或裝飾器類)必須接受乙個函式再返回乙個函式:

# how to define

def wrapper(func1): # 接受乙個callable物件

return func1 # 返回乙個物件,一般為函式

# how to use

def target_func(args): # 目標函式

pass

# 呼叫方式1,直接包裹

result = wrapper(target_func("123"))

# 呼叫方式2,使用@語法,等同於方式1

@wrapper

def target_func(args):

pass

result = target_func()

那麼如果你的裝飾器帶引數呢?那麼你就需要在原來的裝飾器上再包一層,用於接收這些引數。這些引數(私貨)傳遞到內層裝飾器後,閉包就形成了。所以說當你的裝飾器需要自定義引數時,一般都會形成閉包(類裝飾器除外)

def html_tags(tag_name):

def wrapper_(func):

def wrapper(*a程式設計客棧rgs, **kwargs):

content = func(*args, **kwargs)

return ">".format(tag=tag_name, content=content)

return wrapper

return wrapper_

@html_tags('a')

def hello(name='toby'):

return "hello {}!".format(name)

# 不用@的寫法

# hello = html_tags('b')(hello)

# html_tags('b') 是乙個閉包,它接受乙個函式,並返回乙個函式

print(hello()) # hello toby!

print(hello("world")) # hello world!

python閉包詳解 例項演示

python閉包詳解 例項演示 閉包 這個詞語相信大多數學過程式設計的同學並不陌生,但是有時候理解起來還是有一定難度。先看定義 閉包是由函式和與其相關的引用環境組合而成的實體。比如參考資源中就有這樣的的定義 在實現深約束時,需要建立乙個能顯式表示引用環境的東西,並將它與相關的子程式 在一起,這樣 起...

Python中的閉包例項詳解

這篇文章主要介紹了python中的閉包,針對閉包的定義 用法及注意事項進行了例項講解,有助於讀者深入理解閉包的概念及用法,需要的朋友可以參考下 一般來說閉包這個概念在很多語言中都有涉及,本文主要談談python中的閉包定義及相關用法。python中使用閉包主要是在進行函式式開發時使用。詳情分析如下 ...

Python 閉包詳解

一 python變數作用域問題 time 0 全域性變數 def insert time min time time min 區域性變數 return time print insert time 2 print insert time 10 unboundlocalerror local vari...