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...