What’s the Decorator in Python? Decorators are functions which modify the functionality of other functions. It’s greatly useful in Python programming.
To illustrate, see the codes
def a_decorator(func):
def wrapper():
print(‘We can do sth. before a func is called…’)
func()
print(‘… and we can do sth. after it is called…’)
return wrapper()
def a_func():
print(“Hi, I’m a_func!”)
a_func()
a_decorator(a_func)
The above codes can be written with Decorator to modify the functionality of other functions.
def a_decorator(func):
def wrapper():
print(‘We can do sth. before calling a_func…’)
func()
print(‘… and we can do sth. after it was called…’)
return wrapper
@a_decorator
def a_func():
print(“Hi, I’m a_func!”)
a_func()
More typical example with multiple decorators:
def uppercase(func):
def wrapper():
original_result = func()
modified_restult = original_result.upper()
return modified_restult
return wrapper
def strong(func):
def wrapper():
original_result = func()
modified_restult = ‘‘+original_result+’‘
return modified_restult
return wrapper
@uppercase
@strong
def an_output():
return ‘The quick brown fox jumps over the lazy dog.’
print(an_output())
And decorators with parameters:
def a_decorator(func):
def wrapper(*args, **kwargs):
return original_result
# …
return wrapper
def trace(func):
def wrapper(*args, **kwargs):
print(“Trace: You’ve called a function: {func.__name__}(),”,
“with args: {args}; kwargs: {kwargs}”)
orginal_result = func(*args, *kwargs)
print(“Trace: {func.__name__}{args} returned: {orginal_result}”)
return orginal_result
return wrapper
@trace
def say_hi(greeting, name=None):
return greeting + ‘! ‘ + name + ‘.’
print(say_hi(‘Hello’, ‘Jack’))
We should distinguish the other usage of decorator – @property to getter & setter, compare
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
def number_of_wheels(self):
return self.number_of_wheels
def set_number_of_wheels(self, number):
self.number_of_wheels = number
with getter and setter
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
@property
def number_of_wheels(self):
return self.number_of_wheels
@number_of_wheels.setter
def number_of_wheels(self, number):
self.number_of_wheels = number
To get the full understanding of Getter Setter @property(decorator), discussion about scope, private/public variable, and encapsulation is needed.
The following codes should be inspected and studied thoroughly to get the sense of encapsulation. A clear positioning of variables is vital important in coding.
class Golem:
__population = 0
__life_span = 10
def __init__(self, name=None):
self.name = name
self.built_year = datetime.date.today().year
self.__active = True
Golem.__population += 1
def say_hi(self):
print(‘Hi!’)
def cease(self):
self.__active = False
Golem.__population -= 1
def is_active(self):
if datetime.date.today().year – self.built_year >= Golem.__life_span:
self.cease
return self.__active
@property
def population(self):
return Golem.__population
@population.setter
def population(self, value):
Golem.__population = value
g = Golem(‘Clay’)
g.population
g.population = 100
ga = Golem(‘New’)
g.population
ga.population
help(Golem)
Golem.__dict__
g.__dict__
hasattr(Golem, ‘population’)
getattr(Golem, ‘population’)
setattr(Golem, ‘population’, 10000)
g.population
(examples referenced from xiaolai li)
Assessing a function you wrote in terms of it’s executing speed is commonly needed, so we can use decorator for this purpose.
def timer(func):
def wrapper(*args, **kw):
t1=time.time()
# 这是函数真正执行的地方
func(*args, **kw)
t2=time.time()
# 计算下时长
cost_time = t2-t1
print("花费时间:{}秒".format(cost_time))
return wrapper
import time
@timer
def greet(inputstr):
print(inputstr)
time.sleep(5)
greet('dsfere')
Additionally, we shall use the log decorator often in our work. A simple but illustrative example is
def logger(func):
def wrapper(*args, **kw):
print(‘ready to execute,{}function:’.format(func.__name__))
# actual line to be executed is func(*args, **kw)
print(‘job is complete’) return wrapper
@loggerdef add(x, y): print(‘{} + {} = {}’.format(x, y, x+y))
add(200, 50)