在一些語言中,在函數(shù)中可以(嵌套)定義另一個函數(shù)時,如果內(nèi)部的函數(shù)引用了外部的函數(shù)的變量,則可能產(chǎn)生閉包。閉包可以用來在一個函數(shù)與一組“私有”變量之間創(chuàng)建關聯(lián)關系。在給定函數(shù)被多次調(diào)用的過程中,這些私有變量能夠保持其持久性。
——?維基百科
def make_printer(msg):
def printer():
print msg # 夾帶私貨(外部變量)
return printer # 返回的是函數(shù),帶私貨的函數(shù)
printer = make_printer('Foo!')
printer()
閉包在Python中很常見,只不過你沒特別注意這就是一個閉包。比如Python中的裝飾器Decorator,假如你需要寫一個帶參數(shù)的裝飾器,那么一般都會生成閉包
#不帶參數(shù)的裝飾器
def debug(func):
def wrapper(*args, **kwargs): # 指定宇宙無敵參數(shù)
print "[DEBUG]: enter {}()".format(func.__name__)
print 'Prepare and say...',
return func(*args, **kwargs)
return wrapper # 返回
@debug
def say(something):
print "hello {}!".format(something)
?
帶參數(shù)的裝飾器:
def logging(level):
def wrapper(func):
def inner_wrapper(*args, **kwargs):
print "[{level}]: enter function {func}()".format(
level=level,
func=func.__name__)
return func(*args, **kwargs)
return inner_wrapper
return wrapper
@logging(level='INFO')
def say(something):
print "say {}!".format(something)
# 如果沒有使用@語法,等同于
# say = logging(level='INFO')(say)
@logging(level='DEBUG')
def do(something):
print "do {}...".format(something)
if __name__ == '__main__':
say('hello')
do("my work")
如果你的裝飾器如果帶參數(shù),就需要在原來的裝飾器上再包一層,用于接收這些參數(shù)。這些參數(shù)(私貨)傳遞到內(nèi)層的裝飾器里后,閉包就形成了。所以說當你的裝飾器需要自定義參數(shù)時,一般都會形成閉包。(類裝飾器例外)
類裝飾器
class logging(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print "[DEBUG]: enter function {func}()".format(
func=self.func.__name__)
return self.func(*args, **kwargs)
@logging
def say(something):
print "say {}!".format(something)
像
__call__
這樣前后都帶下劃線的方法在Python中被稱為內(nèi)置方法,有時候也被稱為魔法方法。
帶參數(shù)的類裝飾器:
class logging(object):
def __init__(self, level='INFO'):
self.level = level
def __call__(self, func): # 接受函數(shù)
def wrapper(*args, **kwargs):
print "[{level}]: enter function {func}()".format(
level=self.level,
func=func.__name__)
func(*args, **kwargs)
return wrapper #返回函數(shù)
@logging(level='INFO')
def say(something):
print "say {}!".format(something)
內(nèi)置的裝飾器#
內(nèi)置的裝飾器和普通的裝飾器原理是一樣的,只不過返回的不是函數(shù),而是類對象,所以更難理解一些
@property
@staticmethod,@classmethod
更多文章、技術(shù)交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
