Q. Decorator

A decorator in Python is any callable Python object that is used to modify a function or a class. A reference to a function "func" or a class "C" is passed to a decorator and the decorator returns a modified function or class.

Decorator 只有一個參數, 可以是 function "func" 或是 class object. 然後decorator回傳一個附加功能的function or class

We have two different kinds of decorators in Python:

  • Function decorators
  • Class decorators

Q.Functions inside Functions

就把function也想成是一個class, 因為在python中, 任何東西都是object, 這樣就比較好理解

def temperature(t): 
    def celsius2fahrenheit(x):
        return 9 * x / 5 + 32

    result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" 
    return result

print(temperature(20))

The output

It's 68.0 degrees!

Example2

def f():
    def g():
        print("Hi, it's me 'g'")
        print("Thanks for calling me")

    print("This is the function 'f'")
    print("I am calling 'g' now:")
    g()

f()

The output

This is the function 'f' 
I am calling 'g' now:
Hi, it's me 'g'
Thanks for calling me

Q.Functions as Parameters

def g(): 
    print("Hi, it's me 'g'")
    print("Thanks for calling me")

def f(func):
    print("Hi, it's me 'f'")
    print("I will call 'func' now")
    func()
    print("func's real name is " + func.__name__)

f(g)

Another example:

import math 

def foo(func):
    print("The function " + func.__name__ + " was passed to foo")
    res = 0
    for x in [1, 2, 2.5]:
        res += func(x)
    return res

print(foo(math.sin))
print(foo(math.cos))

Q. Functions returning Functions

def f(x): 
    def g(y):
        return y + x + 3 
    return g

nf1 = f(1)
nf2 = f(3)

print(nf1(1))
print(nf2(1))

Another example

def polynomial_creator(a, b, c): 
    def polynomial(x):
        return a * x**2 + b * x + c
    return polynomial

p1 = polynomial_creator(2, 3, -1)
p2 = polynomial_creator(-1, 2, 1)

for x in range(-2, 2, 1):
    print(x, p1(x), p2(x))

Q. A Simple Decorator

The decoration occurrs in the line before the function header. The "@" is followed by the decorator function name.

def our_decorator(func): 
    def function_wrapper(x):
        print("Before calling " + func.__name__)
        func(x)
        print("After calling " + func.__name__)
    return function_wrapper

def foo(x):
    print("Hi, foo has been called with " + str(x))

@our_decorator
def foo(x):
    print("Hi, foo has been called with " + str(x))

foo("Hi")

It is also possible to decorate third party functions, e.g. functions we import from a module. We can't use the Python syntax with the "at" sign in this case:

from math import sin, cos 
def our_decorator(func):
    def function_wrapper(x):
        print("Before calling " + func.__name__)
        res = func(x)
        print(res)
        print("After calling " + func.__name__)
    return function_wrapper

# We now decorate sin and cos with our_decorator
sin = our_decorator(sin)
cos = our_decorator(cos)

for f in [sin, cos]:
    f(3.1415)

Q. Using a Class as a Decorator

We will rewrite the following decorator as a class:

def decorator1(f): 
    def helper():
        print("Decorating", f.__name__)
        f()
    return helper

@decorator1
def foo():
    print("inside foo()")

foo()
class decorator2(object): 
    def __init__(self, f):
        self.f = f

    def __call__(self):
        print("Decorating", self.f.__name__)
        self.f()

@decorator2
def foo():
    print("inside foo()")

foo()

Both versions return the same output:

Decorating foo

inside foo()

results matching ""

    No results matching ""