Python3基础-函数装饰器decorator
装饰器decorator
- 定义:
本质是函数,(装饰其他函数)就是为了给其他函数添加附加功能
- 特性:
不能修改被装饰的函数体内容
不能修改被装饰的函数调用方式
- 嵌套函数+闭包+高阶函数组成
- 闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)
===引入概念:
- 不改变函数体内容
def wrapper(func):
print('starting')
func()
print('stopping')
def test():
print('ok')
wrapper(test)
结果:
starting
ok
stopping
Q:可是改变了原来函数的调用方式,如何完善才能保持原有的函数调用?我们试试装饰函数再嵌套一层函数……
- 不改变函数体原有调用方式
def decorartor(func):
def wrapper():
print( 'starting')
func()
print('stopping')
return wrapper
def test():
print('ok')
test=decorartor(test)#把test当作参数传入装饰函数中
test()
结果:
starting
ok
stopping
so:我们已经通过嵌套函数+高阶函数+返回值完成了对函数体的装饰
使用 decorator 可以使用 python 提供的方法 @ ,避免去编写函数 f=decorator(f) 出现错误
def decorartor(func):
def wrapper():
print( 'starting')
func()
print('stopping')
return wrapper
@decorartor#test=decorartor(test)把test当作参数传入装饰函数中
def test(): print('ok') test()
结果:
starting
ok
stopping
下面我们进一步深入装饰器函数:
- 无参装饰函数
def decorartor(func):
def wrapper(*args,**kwargs):
print( 'starting')
func(*args,**kwargs)
print('stopping')
return wrapper
@decorartor
def test(n):
print('in the test arg is %s' % n)
test('Ronny')
- 有参装饰函数
实例:增加调用对象obj_name(增加一个参数,可以查看谁调用过原函数==给装饰器一个可输出的变量,如何传入参数?)
def decorartor_obj(cobj_name):#传入增加的参数
def f_obj(fun):#传入函数
def wrapper(*args,**kwargs):
print('%sstarting'%obj_name)#引用外层函数变量==闭包
func(*args, **kwargs)
print('stopping')
return wrapper
return f_obj
@decorartor_obj('Ronny')
#可以解释为:
#fun_obj=decorartor_obj('Ronny')
#test_obj=fun_obj(test_obj)
def test_obj(n):
print('in the test arg is %s' % n)
test_obj(2)
结果:
Ronnystarting
in the test arg is 1
stopping
- 装饰器的优化完善
functools.wraps(fuc)
#在装饰器中装饰函数改变了原函数的__doc__ __name__等其它属性
def log(f):
def wrapper(*args, **kw):
print ('call...')
return f(*args, **kw)
return wrapper
@log
def f2(x):
pass
print( f2.__name__)
结果:
wrapper #改变了__name__属性
完善装饰器
import functools#导入模块
def log(f):
@functools.wraps(f)#等价于wrapper=functools.wraps(wrapper)(f)
def wrapper(*args, **kw):
print ('call...')
return f(*args, **kw)
return wrapper
@log
def f2(x):
pass
print( f2.__name__)
结果:
f
--------------------------------------------------------
补充
——闭包函数
- 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
- 前提:嵌套函数
def counter(num):
count = num
def incr():
print(count)
return incr
f=counter(2)
f()
f_1=counter(20)
f_1()
f()
结果:
2
20
2
——偏函数
functools.partial
#把函数的某些参数给固定住,返回一个新的函数
#当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
import functools
def students_ifo(name,school):
print('%s from %s'%(name,school))
#假如多少学生都在一个学校,每次调用都需要写入实参会很麻烦,怎么才能更加简单呢?
students_ifo=functools.partial(students_ifo,school='北京大学')
students_ifo('Ronny')
students_ifo('Roman')
结果:
Ronny from 北京大学
Roman from 北京大学

浙公网安备 33010602011771号