一.简介
在学习介绍装饰器之前 ,我们需要了解函数 是对象,函数 的特性是:
- 函数可以赋值给一个变量
- 函数可以定义在另一个函数内部
即,这也意味着一个函数可以返回另一个函数
装饰器就是封装器,可以让你在被装饰函数之前或之后执行代码,而不必修改函数本身
所以:
装饰器是一个修改函数、或方法、或类的函数
自定义装饰器
def out(inner): def fun(): print("before") inner() print("after") return fun def inner(): print("center") inner() mydecorated = out(inner) mydecorated()
使用装饰器
def outer(fun): def inn(): print("hello") r = fun() #== f1() return r return inn @outer def f1(): print("test") f1()
装饰器只是装饰器设计模式的python实现,装饰器可以嵌套
#例2
def out(func): def inn(a,b): print('test') r = func(a,b) return r return inn @out def fun1(a, b): sum1 = a + b print(sum1) fun1(1, 2)
装饰器传参
通过在形参列表中使用 *args
语法,python函数能够接收可变数量的位置参数(positional arguments)。 *args
会将所有没有关键字的参数放入一个参数元组中,在函数里可以访问元组中的参数。相反,将 *args
用于函数调用时的实参列表之时,它会将参数元组展开成一系列的位置参数
**kwargs
与 *args
的行为类似,但用于关键字参数而非位置参数。如果在函数的形参列表中使用 **kwargs
,它会收集函数收到的所有额外关键字参数,放入一个字典中。如果用于函数的实参列表,它会将一个字典展开为一系列的关键字参数
def funtion_with_many_keyword_args(**kwargs): print(kwargs) funtion_with_many_keyword_args(a='apples', b='bananas', c='cantalopes')
def multiply_name(count=0, name=''): print(name * count) arg_dict = {'count': 3, 'name': 'Brian'} multiply_name(**arg_dict)
def outer1(func): def inner(*args,**kwargs): print("123") ret = func(*args,**kwargs) print("123") return ret return inner def outer2(func): def inner(*args,**kwargs): print("456") ret = func(*args,**kwargs) print("456") return ret return inner @outer1 @outer2 def f(): return "ok" r = f() print(r) #打印结果: 456 123 ok # 1、执行outer2函数,将f作为outer2函数的参数,将f赋值给func # 2、得到返回值inner,重新赋值给f:f = inner ==> f() = inner() # 3、执行outer1函数,将整个inner函数作为outer1函数的参数 # 4、得到返回值inner,再重新赋值给f:f == inner ==> f() = inner() # 5、因为装饰器只有两层,就不用再执行下一个装饰器函数,如果更多层就继续循环以上程序过程 # 6、下面就执行最终的inner函数,执行func函数时,就是执行最原始的f函数
使用装饰器语法,鸟瞰其中发生的事情(以例2为例):
- 解释器到达被装饰的函数,编译fun1函数,并将其命名为 'fun1'。
- 然后将该函数传递给装饰行中指定的装饰器函数(out)。
- 装饰器函数(通常是用来包装原函数的另一个函数)的返回值取代原来的函数(fun1),绑定到变量名 fun1