啥是装饰器?python
python装饰器本质上就是一个函数,它可让其余函数在不须要作任何代码变更(被装饰的函数调用方式 返回值等不改变)的前提下增长额外的功能,装饰器的返回值也是一个函数对象(函数的指针)web
装饰器做用 是对于咱们已经写好的程序,能够抽离出一些雷同的代码组建多个特定功能的装饰器,这样咱们就能够针对不一样的需求去使用特定的装饰器,这时由于源码去除了大量泛化的内容而使得源码具备更加清晰的逻辑。闭包
装饰器的属性:app
实质: 是一个函数函数
参数:是你要装饰的函数名(并非函数调用)性能
返回:是装饰完的函数名(也非函数调用)测试
做用:为已经存在的对象添加额外的功能spa
特色:不须要对对象作任何的代码上的变更指针
多个装饰器的执行顺序:是从近到远依次执行。日志
装饰器的应用场景:
插入日志、性能测试、事务处理、权限校验、统计函数的执行时间等
在看装饰器以前,咱们先来搞清楚什么是闭包函数:
若是内部函数里引用了外部函数里定义的对象(甚至是外层以外,但不是全局变量),那么此时内部函数就被称为闭包函数。闭包函数所引用的外部定义的变量被叫作自由变量。闭包从语法上看很是简单,可是却有强大的做用。闭包能够将其本身的代码和做用域以及外部函数的做用结合在一块儿
总结:什么函数能够被称为闭包函数呢?主要是知足两点:函数内部定义的函数;引用了外部变量但非全局变量。
装饰器的代码案例
#!/usr/bin/env python3 # -*- coding:utf-8 -*- username, password = 'root', 'root123' def autoLogin(loginType): print('loginType:', loginType) def outWrapp(func): def wrapp(*args, **kwargs): inName = input('username:') inPasswd = input('password:') if inName == username and inPasswd == password : print("login sucess")
else:
print("Invalid login username or password error") return return func(*args, **kwargs) return wrapp return outWrapp @autoLogin(loginType='web') def webLogin(): print('in webLogin funtion'.center(50, '*')) return "webLogin function" @autoLogin(loginType='local') def localLogin(): print('in localLogin funciton'.center(50, '=')) return "localLogin function" webResult = webLogin() print(webResult) localResult = localLogin() print(localResult)
上面的案例 看似完美解决了在不改变原来函数代码的状况下新增了一些功能,也没有改变函数的调用方式。 可是函数的函数名属性却被咱们改变了, 怎么看咱们改变了函数的函数名属性呢, 咱们能够打印一下函数的属性名就知道了 print(webLogin.__name__) 结果返回的不是 webLogin,而是wrapp。这是为何呢? 其实函数名也是一个变量,而装饰器装饰函数实际上是把原来的函数进行包装返回一个闭包函数给原来的变量名。就至关于 def func1(): pass fun=func1 同样 fun.__name__ 返回的就是func1. 那这样不是也相对于改变被装饰的函数了嘛, 有没有一种方法能够解决这个问题呢? 固然有方法, 否则装饰器的特色就变成了缺点。方法就是应用一个包的函数:functools.wraps()
#!/usr/bin/env python3 # -*- coding:utf-8 -*- from functools import wraps def decoratorFun(func): @wraps(func) def innerFunc(): print('in inerFunc') return func() return innerFunc @decoratorFun def outfun(): print('in outfun') print(outfun.__name__) #output: outfun
这样个人装饰器才算完美。