2012年8月11日 星期六

python decorators三種寫法:decorator with arguments(class),decorator without arguments(class),decorator function with arguments

參考來源:http://www.artima.com/weblogs/viewpost.jsp?thread=240845


Decorators without Arguments(class)

注意事項:
1)decorator的__init__(self,f)必須傳入被修飾的函數f
2)decorator的__call__(self,*args)必須傳入被修飾的函數f的參數
3)執行到@decoratorWithoutArguments 時觸發 decorator的__init__方法
4)呼叫sayHello函數時觸發decorator的__call__方法


class decoratorWithoutArguments(object):

    def __init__(self, f):
        """
        If there are no decorator arguments, the function
        to be decorated is passed to the constructor.
        """
        print "Inside __init__()"
        self.f = f

    def __call__(self, *args):
        """
        The __call__ method is not called until the
        decorated function is called.
        """
        print "Inside __call__()"
        self.f(*args)
        print "After self.f(*args)"

@decoratorWithoutArguments
def sayHello(a1, a2, a3, a4):
    print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"
sayHello("say", "hello", "argument", "list")
print "After first sayHello() call"
sayHello("a", "different", "set of", "arguments")
print "After second sayHello() call"



執行結果:

Inside __init__()
After decoration
Preparing to call sayHello()
Inside __call__()
sayHello arguments: say hello argument list
After self.f(*args)

After first sayHello() call
Inside __call__()
sayHello arguments: a different set of arguments
After self.f(*args)
After second sayHello() call
________________________________________

Decorators with Arguments(class)

注意事項:
1) decorator的__init__(self,arg1,arg2,arg3)必須傳入decorator需要的參數數量
例如: @decoratorWithArguments("hello", "world", 42) 共有三個參數設定為arg1,arg2,arg3
2) decorator的__call__(self,f)方法必須傳入被修飾的函數f
3)執行到@decoratorWithArguments("hello", "world", 42)時觸發 decorator的__init__方法
4)呼叫sayHello函數時觸發decorator的__call__方法內部定義的wrapped_f(*args)函數



class decoratorWithArguments(object):

    def __init__(self, arg1, arg2, arg3):
        """
        If there are decorator arguments, the function
        to be decorated is not passed to the constructor!
        """
        print "Inside __init__()"
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

    def __call__(self, f):
        """
        If there are decorator arguments, __call__() is only called
        once, as part of the decoration process! You can only give
        it a single argument, which is the function object.
        """
        print "Inside __call__()"
        def wrapped_f(*args):
            print "Inside wrapped_f()"
            print "Decorator arguments:", self.arg1, self.arg2, self.arg3
            f(*args)
            print "After f(*args)"
        return wrapped_f

@decoratorWithArguments("hello", "world", 42)
def sayHello(a1, a2, a3, a4):
    print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"
sayHello("say", "hello", "argument", "list")
print "after first sayHello() call"
sayHello("a", "different", "set of", "arguments")
print "after second sayHello() call"


執行結果:


Inside __init__()
Inside __call__()
After decoration
Preparing to call sayHello()
Inside wrapped_f()
Decorator arguments: hello world 42
sayHello arguments: say hello argument list
After f(*args)
after first sayHello() call
Inside wrapped_f()
Decorator arguments: hello world 42
sayHello arguments: a different set of arguments
After f(*args)
after second sayHello() call
_______________________________________________________



Decorator Functions with Decorator Arguments

注意事項:
1)decoratorFunctionWithArguments(arg1, arg2, arg3) 的參數arg1,arg2,arg3為了接收
@decoratorFunctionWithArguments("hello", "world", 42) 的參數"hello", "world", 42
2)decoratorFunctionWithArguments內部的wrap(f)函數在執行敘述行,參數f則是為了接收被修飾函數sayHello,並且wrap(f)在程式執行敘述@decoratorFunctionWithArguments("hello", "world", 42) 時觸發
3)呼叫sayHello("say", "hello", "argument", "list")函數時觸發
decoratorFunctionWithArgument內的wrapped_f(*arg)函數


def decoratorFunctionWithArguments(arg1, arg2, arg3):
    def wrap(f):
        print "Inside wrap()"
        def wrapped_f(*args):
            print "Inside wrapped_f()"
            print "Decorator arguments:", arg1, arg2, arg3
            f(*args)
            print "After f(*args)"
        return wrapped_f
    return wrap

@decoratorFunctionWithArguments("hello", "world", 42)
def sayHello(a1, a2, a3, a4):
    print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"
sayHello("say", "hello", "argument", "list")
print "after first sayHello() call"
sayHello("a", "different", "set of", "arguments")
print "after second sayHello() call"
執行結果:

沒有留言:

張貼留言