python裝飾器

今天看了一些函數裝飾器的知識,第一遍沒看懂,後來才一點點弄明白。。。html

首先,函數也是對象,因此能夠返回函數函數

def hello(func):  #func是函數名學習

    def h():#在函數內部的函數ui

        print 'hello world'spa

        func().net

    return hcode

@hello htm

def d():對象

    print 'charles dong !'blog

d() 

輸出:

‘hello world’

‘charles dong’

裝飾器也能夠有參數

def deco(arg):#arg='mymodule'
def _deco(func):#func=myfunc()
def __deco():
print ( "before %s called [%s]." % (func.__name__, arg))
func()
print ( " after %s called [%s]." % (func.__name__, arg))
return __deco
return _deco
@deco ( "mymodule" )
def myfunc():
print ( " myfunc() called." )

 這是在Python學習小組上介紹的內容,現學現賣、多練習是好的學習方式。

第一步:最簡單的函數,準備附加額外功能

?
1
2
3
4
5
6
7
8
# -*- coding:gbk -*-
'''示例1: 最簡單的函數,表示調用了兩次'''
def myfunc():
print ( "myfunc() called." )
myfunc()
myfunc()

第二步:使用裝飾函數在函數執行前和執行後分別附加額外功能

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding:gbk -*-
'''示例2: 替換函數(裝飾)
裝飾函數的參數是被裝飾的函數對象,返回原函數對象
裝飾的實質語句: myfunc = deco(myfunc)'''
def deco(func):
print ( "before myfunc() called." )
func()
print ( " after myfunc() called." )
return func
def myfunc():
print ( " myfunc() called." )
myfunc = deco(myfunc)
myfunc()
myfunc()

第三步:使用語法糖@來裝飾函數

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- coding:gbk -*-
'''示例3: 使用語法糖@來裝飾函數,至關於「myfunc = deco(myfunc)」
但發現新函數只在第一次被調用,且原函數多調用了一次'''
def deco(func):
print ( "before myfunc() called." )
func()
print ( " after myfunc() called." )
return func
@deco
def myfunc():
print ( " myfunc() called." )
myfunc()
myfunc()

第四步:使用內嵌包裝函數來確保每次新函數都被調用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding:gbk -*-
'''示例4: 使用內嵌包裝函數來確保每次新函數都被調用,
內嵌包裝函數的形參和返回值與原函數相同,裝飾函數返回內嵌包裝函數對象'''
def deco(func):
def _deco():
print ( "before myfunc() called." )
func()
print ( " after myfunc() called." )
# 不須要返回func,實際上應返回原函數的返回值
return _deco
@deco
def myfunc():
print ( " myfunc() called." )
return 'ok'
myfunc()
myfunc()

第五步:對帶參數的函數進行裝飾

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding:gbk -*-
'''示例5: 對帶參數的函數進行裝飾,
內嵌包裝函數的形參和返回值與原函數相同,裝飾函數返回內嵌包裝函數對象'''
def deco(func):
def _deco(a, b):
print ( "before myfunc() called." )
ret = func(a, b)
print ( " after myfunc() called. result: %s" % ret)
return ret
return _deco
@deco
def myfunc(a, b):
print ( " myfunc(%s,%s) called." % (a, b))
return a + b
myfunc( 1 , 2 )
myfunc( 3 , 4 )

第六步:對參數數量不肯定的函數進行裝飾

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding:gbk -*-
'''示例6: 對參數數量不肯定的函數進行裝飾,
參數用(*args, **kwargs),自動適應變參和命名參數'''
def deco(func):
def _deco( * args, * * kwargs):
print ( "before %s called." % func.__name__)
ret = func( * args, * * kwargs)
print ( " after %s called. result: %s" % (func.__name__, ret))
return ret
return _deco
@deco
def myfunc(a, b):
print ( " myfunc(%s,%s) called." % (a, b))
return a + b
@deco
def myfunc2(a, b, c):
print ( " myfunc2(%s,%s,%s) called." % (a, b, c))
return a + b + c
myfunc( 1 , 2 )
myfunc( 3 , 4 )
myfunc2( 1 , 2 , 3 )
myfunc2( 3 , 4 , 5 )

第七步:讓裝飾器帶參數

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding:gbk -*-
'''示例7: 在示例4的基礎上,讓裝飾器帶參數,
和上一示例相比在外層多了一層包裝。
裝飾函數名實際上應更有意義些'''
def deco(arg):
def _deco(func):
def __deco():
print ( "before %s called [%s]." % (func.__name__, arg))
func()
print ( " after %s called [%s]." % (func.__name__, arg))
return __deco
return _deco
@deco ( "mymodule" )
def myfunc():
print ( " myfunc() called." )
@deco ( "module2" )
def myfunc2():
print ( " myfunc2() called." )
myfunc()
myfunc2()

第八步:讓裝飾器帶 類 參數

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# -*- coding:gbk -*-
'''示例8: 裝飾器帶類參數'''
class locker:
def __init__( self ):
print ( "locker.__init__() should be not called." )
@staticmethod
def acquire():
print ( "locker.acquire() called.(這是靜態方法)" )
@staticmethod
def release():
print ( " locker.release() called.(不須要對象實例)" )
def deco( cls ):
'''cls 必須實現acquire和release靜態方法'''
def _deco(func):
def __deco():
print ( "before %s called [%s]." % (func.__name__, cls ))
cls .acquire()
try :
return func()
finally :
cls .release()
return __deco
return _deco
@deco (locker)
def myfunc():
print ( " myfunc() called." )
myfunc()
myfunc()

第九步:裝飾器帶類參數,並分拆公共類到其餘py文件中,同時演示了對一個函數應用多個裝飾器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# -*- coding:gbk -*-
'''mylocker.py: 公共類 for 示例9.py'''
class mylocker:
def __init__( self ):
print ( "mylocker.__init__() called." )
@staticmethod
def acquire():
print ( "mylocker.acquire() called." )
@staticmethod
def unlock():
print ( " mylocker.unlock() called." )
class lockerex(mylocker):
@staticmethod
def acquire():
print ( "lockerex.acquire() called." )
@staticmethod
def unlock():
print ( " lockerex.unlock() called." )
def lockhelper( cls ):
'''cls 必須實現acquire和release靜態方法'''
def _deco(func):
def __deco( * args, * * kwargs):
print ( "before %s called." % func.__name__)
cls .acquire()
try :
return func( * args, * * kwargs)
finally :
cls .unlock()
return __deco
return _deco
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding:gbk -*-
'''示例9: 裝飾器帶類參數,並分拆公共類到其餘py文件中
同時演示了對一個函數應用多個裝飾器'''
from mylocker import *
class example:
@lockhelper (mylocker)
def myfunc( self ):
print ( " myfunc() called." )
@lockhelper (mylocker)
@lockhelper (lockerex)
def myfunc2( self , a, b):
print ( " myfunc2() called." )
return a + b
if __name__ = = "__main__" :
a = example()
a.myfunc()
print (a.myfunc())
print (a.myfunc2( 1 , 2 ))
print (a.myfunc2( 3 , 4 ))



實現一個裝飾器d2使下面的代碼打印相應的結果:

 @d2('a', 'b')

def test(arg1, arg2):

    print 'test', arg1, arg2

 

test('c', 'd')

 

[output]

before test a b

test c d

[/output]


def d2(a,b):

    def dd2(func):

        def ddd2(arg1,arg2):

            print '[output]'

            print 'befot test', a, b

            test(argv1, argv2)

            print '[/output]'

            return ddd2

    return dd2

相關文章
相關標籤/搜索