python装饰器 和单例模式
闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包。
内嵌函数:
1 def foo(): 2 def bar(): 3 print('bar() called') 4 print ('foo() called') 5 return bar 6 7 >>>f = foo() 8 foo() called 9 >>>f() 10 bar() called
相当于:
1 def foo(): 2 def bar(): 3 print('bar() called') 4 print ('foo() called') 5 return bar() 6 7 >>>foo() 8 foo() called 9 bar() called
装饰器:是一个实现了给现有函数添加装饰功能的函数,就是把原来的函数给包了起来,在不改变原函数代码的情况下,在外面起到了装饰作用
- 它的参数是需要被装饰的函数
- 返回值是新定义的一个包装了原有函数的函数。
在被装饰的函数前使用@符号指定装饰器,在运行程序的时候,Python解释器会根据@标注自动生成装饰器函数,并调用装饰器函数。
带参数的函数:
1 import time 2 3 def timer(func): 4 '''统计函数运行时间的装饰器''' 5 def wrapper(*args, **kwargs): 6 start = time.time() 7 func(*args, **kwargs) 8 end = time.time() 9 used = end - start 10 print(f'{func.__name__} used {used}') 11 return wrapper
- wrapper使用了通配符,*args代表所有的位置参数,**kwargs代表所有的关键词参数。这样就可以应对任何参数情况。
- wrapper调用被装饰的函数的时候,只要原封不动的把参数再传递进去就可以了。
函数返回值:
如果被装饰的函数func有返回值,wrapper也只需把func的返回值返回就可以了。
1 import time 2 3 def timer(func): 4 '''统计函数运行时间的装饰器''' 5 def wrapper(*args, **kwargs): 6 start = time.time() 7 ret_value = func(*args, **kwargs) 8 end = time.time() 9 used = end - start 10 print(f'{func.__name__} used {used}') 11 return ret_value 12 return wrapper 13 14 @timer 15 def add(num1, num2): 16 return num1 + num2 17 18 sum = add(5, 8) 19 print(sum)
代码调试:
现在我们来创建一个装饰器:它会打印函数的参数,以及返回值。
如果你有实际项目经验,你一定会知道这个很有用。这不就是自动打印日志嘛!
1 def debug(func): 2 def wrapper_debug(*args, **kwargs): 3 print(f'{func.__name__}:{args}, {kwargs}') 4 ret_val = func(*args, **kwargs) 5 print(f'return: {ret_val}') 6 return ret_val 7 return wrapper_debug 8 9 @debug 10 def add(a, b): 11 return a + b 12 13 add(1, 3) 14 add(2, 3) 15 add(4, 3)
装饰器模版:
1 def decorator(func): 2 def wrapper_decorator(*args, **kwargs): 3 #调用前操作 4 ret_val = func(*args, **kwargs) 5 #调用后操作 6 return ret_val 7 return wrapper_decorator
按照这个模板:
- 修改装饰器的名字,把decorator替换为具体的名字。
- 在注释“调用前操作”的地方写自己想写的代码
在注释“调用后操作”的地方写自己想写的代码。