Decorator concept
Passing a function as an argument to another function returns an alternative version of the function
The way to dynamically add functionality during code execution, called decorators, is essentially a function that returns a function with the purpose of adding functionality to the function without changing the original function.
Decorator 1
1. A function is also an object, and a function object can be assigned to a variable, so it can also be called through a variable.
Definition of function say ()
def fun(): print('hello python')
Assuming you want to enhance the capabilities of the say() function, such as making positive and negative judgments on arguments when calling a function, but you don't want to modify the definition of say(), you can add functionality while the code is running by using an adorner.
It can be defined as follows:
def outer(f): def inner(): print('@@@@@@@') f() print('!!!!') return inner
Look at the outer() function above, because it is a decorator, so it takes a function as a parameter and returns a function.Place decorator at function definition with python's syntax sugar
@outer def fun(): print('hello python')
Putting the syntax sugar @outer at the definition of the fun() function is equivalent to executing a statement:
Since outer() is only a decorator and returns a function, the original fun() function still exists, but now the fun() variable with the same name points to a new function, so calling your fun() will execute the new function, that is, the inner() function returned in the outer() function.
fun = outer(fun)
Calling the fun() function not only runs fun() itself, but also prints out new content:
Example:
def outer(f): def inner(age): if age <=0: age = 0 f(age) return inner @outer #Grammatical Sugar def say(age): print('%d years old' %(age))
Executing say (-12) results in
Decorator 2
Decorator implements a function timer
1. What if the decorated function has a return value?
2. How do I keep the function name and help documentation information of the decorated function?Decorator implements a function timer
1. What if the decorated function has a return value?
2. How do I keep the function name and help documentation information of the decorated function?
import random import string import time li = [random.choice(string.ascii_letters) for i in range(100)] def timeit(fun): #@functools.wraps(fun) def wrapper(*args,**kwargs):# Receive variable and keyword parameters """This is an ornament timeit""" # Before function execution start_time = time.time() # Execute Function res = fun(*args,**kwargs) # After function execution stop_time = time.time() print('The run event is:%.6f' %(stop_time-start_time)) return res return wrapper # @timeit # def con_add(): # s = '' # for i in li: # s += (i + '') # print(s) # @timeit # def join_add(): # print(','.join(li)) # # con_add() # join_add() @timeit def fun_list(n): """This is fun_list function""" return [2 * i for i in range(n)] @timeit def fun_map(n): """This is fun_map Function Decoration timeis decorate""" return list(map(lambda x:x*2,range(n))) # fun_list(10000) # fun_map(10000)
print(fun_list.__name__) print(fun_list.__doc__) print(fun_map.__name__) print(fun_map.__doc__)
Decoration 3
To create an ornament, the following requirements are required:
- Create an add_log decorator, and the decorated function prints the log information;
- The log format is: [string time] function name: xxx, run time: xxx,
Run Return Value Result: xxx
# import time # print(time.ctime()) import time import functools def add_log(func): @functools.wraps(func) def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) end_time = time.time() print('[%s] Function name:%s,Runtime:%.6f,Result of running the return value' ':%d' %(time.ctime(),func.__name__, end_time-start_time,res)) return res return wrapper @add_log def add(x,y): time.sleep(1) return x+y add(1,10)
Decorator 4
- Basic (parameterless decorator)
Write the decorator required_ints under the following conditions:
1). Ensure that every parameter received by the function is an integer;
2). If the parameter is not an integer, print TypeError: the parameter must be an integer
import functools def required_ints(func): @functools.wraps(func) def wrapper(*args, **kwargs): # args=(1,2,..) for i in args: # if isinstance(i,int): # pass # else: # print('Not all arguments to the function are int') # break if not isinstance(i, int): print('Not all parameters of a function are int type') break else: res = func(*args, **kwargs) return res return wrapper @required_ints def add(a, b): return a + b @required_ints def mymax(a,b,c,d): return max(a,b,c,d) print(add(1,2.0))
To create an ornament, the following requirements are required:
- Create an add_log decorator, and the decorated function prints the log information;
- The log format is: [string time] function name: xxx, run time: xxx, run return value result: XXX
import time import functools def log(kind): def add_log(func): @functools.wraps(func) def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) end_time = time.time() print('<%s> [%s] Function name:%s,Runtime:%.6f,Result of running the return value' ':%d' %(kind,time.ctime(),func.__name__, end_time-start_time,res)) return res return wrapper return add_log @log('local2') def add(x,y): time.sleep(1) return x+y add(1,10)
Decorator 5
['root','admin','redhat']
id id+vip
Scenarios for multiple decorators:
Multiple decorators will be used to verify successful login before verifying that permissions are sufficient
import functools import inspect def is_login(fun): @functools.wraps(fun) def warapper(*args, **kwargs): # ('admin',) if args[0] in login_session: temp = fun(*args, **kwargs) return temp else: print('Error:%s No landing success' % (args[0])) return warapper def is_admin(fun): @functools.wraps(fun) # nspect.getcallargs returns a dictionary # key:formal parameter value:corresponding argument def wrapper(*args, **kwargs): inspect_res = inspect.getcallargs(fun, *args, **kwargs) print('inspect The return value of:%s' % (inspect_res)) if inspect_res.get('name') == 'root': temp = fun(*args, **kwargs) return temp else: print('not root user,no permisson add user') return wrapper login_session = ['root', 'admin', 'redhat'] @is_login @is_admin def add_user(name): print('add_user~~') add_user('root')
Decorator 6
- Basic (parameterless decorator)
Write the decorator required_ints under the following conditions:
1). Ensure that every parameter received by the function is an integer;
2). If the parameter is not an integer, print TypeError: the parameter must be an integer
import functools def required_ints(func): @functools.wraps(func) def wrapper(*args, **kwargs): # args=(1,2,..) for i in args: # if isinstance(i,int): # pass # else: # print('Not all arguments to the function are int') # break if not isinstance(i, int): print('Not all parameters of a function are int type') break else: res = func(*args, **kwargs) return res return wrapper @required_ints def add(a, b): return a + b @required_ints def mymax(a,b,c,d): return max(a,b,c,d) print(add(1,2.0))
Decorator 7
To create an ornament, the following requirements are required:
- Create an add_log decorator, and the decorated function prints the log information;
- The log format is: [string time] function name: xxx, run time: xxx, run return value result: XXX
import time import functools def log(kind): def add_log(func): @functools.wraps(func) def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) end_time = time.time() print('<%s> [%s] Function name:%s,Runtime:%.6f,Result of running the return value' ':%d' %(kind,time.ctime(),func.__name__, end_time-start_time,res)) return res return wrapper return add_log @log('local2') def add(x,y): time.sleep(1) return x+y add(1,10)
Decorator 8
- Upgraded version (decorator with parameters)
Write the decorator required_types under the following conditions:
1). When the decorator is @required_types(int,float), make sure that every parameter the function receives is
int or float type;
2). When the decorator is @required_types(list), make sure that every parameter received by the function is a list type;
3. When the decorator is @required_types(str,int), make sure that each parameter received by the function is of type STR or int;
4). If the parameter does not meet the criteria, print TypeError: the parameter must be of type XXX
import functools def required_type(*kind): def required(fun): @functools.wraps(fun) def wrapper(*args,**kwargs): for i in args: if not isinstance(i,kind): print('Not all parameters of a function',kind) break else: res = fun(*args,**kwargs) return res return wrapper return required @required_type(int) def add(a, b): return a + b print(add(1,1.2))