很多python的代碼都帶有裝飾器=。=
現(xiàn)在不學以后也要學
學一下裝飾器
閉包
在學裝飾器之前先看看python的閉包
在一些語言中泥张,在函數(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()
閉包就是當某個函數(shù)被當成對象返回時粤剧,夾帶了外部變量歇竟,就形成了一個閉包。
而如果內(nèi)部函數(shù)里引用了外部函數(shù)里定義的對象(甚至是外層之外抵恋,但不是全局變量)焕议,那么此時內(nèi)部函數(shù)就被稱為閉包函數(shù)。閉包函數(shù)所引用的外部定義的變量被叫做自由變量弧关。閉包從語法上看非常簡單盅安,但是卻有強大的作用。閉包可以將其自己的代碼和作用域以及外部函數(shù)的作用結合在一起世囊。下面給出一個簡單的閉包的例子:
def count(a):
b = 1
def sum():
c = 1
return a + c # a是自由變量
return sum
print count(a = 2)() # 3
裝飾器
python裝飾器本質(zhì)上就是一個函數(shù)别瞭,它可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外的功能,裝飾器的返回值也是一個函數(shù)對象(函數(shù)的指針)
裝飾器的屬性
- 實質(zhì): 是一個函數(shù)
- 參數(shù):是你要裝飾的函數(shù)名(并非函數(shù)調(diào)用)
- 返回:是裝飾完的函數(shù)名(也非函數(shù)調(diào)用)
- 作用:為已經(jīng)存在的對象添加額外的功能
- 特點:不需要對對象做任何的代碼上的變動
python裝飾器有很多經(jīng)典的應用場景株憾,比如:插入日志蝙寨、性能測試、事務處理嗤瞎、權限校驗等墙歪。裝飾器是解決這類問題的絕佳設計。并且從引入中的列子中我們也可以歸納出:裝飾器最大的作用就是對于我們已經(jīng)寫好的程序贝奇,我們可以抽離出一些雷同的代碼組建多個特定功能的裝飾器虹菲,這樣我們就可以針對不同的需求去使用特定的裝飾器,這時因為源碼去除了大量泛化的內(nèi)容而使得源碼具有更加清晰的邏輯
裝飾器也分為函數(shù)裝飾器和類裝飾器
在python2.4之前的裝飾器是這樣的
def debug(func):
def wrapper():
print "[DEBUG]: enter {}()".format(func.__name__)
return func()
return wrapper
def say_hello():
print "hello!"
say_hello = debug(say_hello) # 添加功能并保持原函數(shù)名不變
其實裝飾器的原理就跟這個差不多他返回的就是wrapper 會把原來的覆蓋了
跟現(xiàn)在的裝飾器的意思是一樣的
def debug(func):
def wrapper():
print "[DEBUG]: enter {}()".format(func.__name__)
return func()
return wrapper
@debug
def say_hello():
print "hello!"
只不過更加簡便少了一步賦值的步驟
函數(shù)裝飾器
上面的都是函數(shù)裝飾器
def debug(func):
def wrapper():
print "[DEBUG]: enter {}()".format(func.__name__)
return func()
return wrapper
@debug
def say_hello():
print "hello!"
say_hello()
類裝飾器
裝飾器函數(shù)其實是這樣一個接口約束掉瞳,它必須接受一個callable對象作為參數(shù)毕源,然后返回一個callable對象浪漠。在Python中一般callable對象都是函數(shù)
只要當前的類中有一個__call__
函數(shù)就可以讓該對象編程callable對象
只要用__init__
來初始化, __call__
來返回函數(shù)就可以了
class debug():
def __init__(self, func):
self.func = func
def __call__(self):
print "[DEBUG]: enter {func}()".format(
func=self.func.__name__)
return self.func()
@debug
def say_hello():
print "say hello!"
say_hello()
這樣就好了
跟原來的函數(shù)裝飾器差不多
參考鏈接
https://betacat.online/posts/2016-10-23/python-closure/
https://www.cnblogs.com/cicaday/p/python-decorator.html