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()