python——装饰器
Posted 寻寻觅觅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python——装饰器相关的知识,希望对你有一定的参考价值。
一、名称空间(name space)
存放名字的地方,存什么名字呢?
如变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方
名称空间共3种:
- locals: 是函数内的名称空间,包括局部变量和形参
- globals: 全局变量,函数定义所在模块的名字空间
- builtins: 内置模块的名字空间
不同变量的作用域不同就是由这个变量所在的命名空间决定的。
作用域即范围
- 全局范围:全局存活,全局有效
- 局部范围:临时存活,局部有效
查看作用域方法 globals(),locals()
作用域查找顺序:
locals -> enclosing function(相邻的) -> globals -> __builtins__ (LEGB)
二、闭包
有一下代码:
def outer(): name = ‘alex‘ def inner(): print("在inner里打印外层函数的变量",name) return inner f = outer() f() 输出: 在inner里打印外层函数的变量 alex
外层函数outer返回了内层函数的函数名inner给变量f,在函数外部执行语句:f()是就相当于调用了内层函数inner,并且inner又引用了外层函数的变量name。
对于这种,外层函数返回子函数的函数名(即子函数内存地址),在函数外调用了子函数,子函数又引用了外层函数的变量,就形成了闭包。
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
三、装饰器
可以理解为一种装饰函数的工具,其本质就是一个函数。
软件开发的原则之一:开放—封闭原则
开放:对现有功能的扩展开放
封闭:已实现的功能代码块不应该被修改
所以,装饰器的原则是:
1、不能修改被装饰函数的源码
2、不能修改被装饰函数的调用方式
高阶函数+嵌套函数=装饰器
高阶函数:1、将函数名作为实参传递给另一个函数(不改变源码)
2、return返回另一个函数名(不改变函数的调用方式)
装饰器实例
你是一家视频网站的后端开发工程师,你们网站已上线运行了该模块:
def home(): print("---首页----") def america(): print("----欧美专区----") def japan(): print("----日韩专区----") def henan(): print("----河南专区----") home() america() japan() henan()
现在,你们老板跟你说,现在用户越来越多啦,准备将"america"和"henan"两个板块改为收费才能进入,所以你就要给它们新增一个登陆认证的功能,但是系统已经上线了,你是不可能修改源码的,用户一直也都习惯了这种调用方式去进去各板块,所以你想到了装饰器:
status = False # 用于判断用户登录状态 def auth(func): # 将函数作为参数传入 func=america or func = henan def inner(): global status # 定义全局变量 _username = "qwe" # 假设这是数据库用户信息 _password = "123" if status is False: # 未登录 username = input("username:") password = input("password:") if username == _username and password == _password: # 用户名与密码是否正确 print("\033[35;1m-----Welcome-----\033[0m") status = True # 修改用户登录状态 else: print("Wrong username or password") if status is True: # 已登录 print("\033[35;1m-----用户已登录-----\033[0m") func() # 允许进入相关板块 america() or henan() return inner # 返回内层函数名 def home(): print("---首页----") @auth # 给函数加上装饰器,相当于执行:auth(america) ,稍后auth 会将函数inner返回,即america=inner def america(): print("----欧美专区----") def japan(): print("----日韩专区----") @auth # 给函数加上装饰器 def henan(): print("----河南专区----") home() america() # 此时的america已经被“偷梁换柱”,相当于inner() japan() henan() # inner() 输出: ---首页---- username:qwe password:123 -----Welcome----- -----用户已登录----- ----欧美专区---- ----日韩专区---- -----用户已登录----- ----河南专区----
你可以在里面传参数,最好使用非固定参数,因为万一有些函数你要传参,有些不用,方便动态管理:
status = False # 用于判断用户登录状态 def auth(func): # 将函数作为参数传入 func=america or func = henan def inner(*args, **kwargs): global status # 定义全局变量 _username = "qwe" # 假设这是数据库用户信息 _password = "123" if status is False: # 未登录 username = input("username:") password = input("password:") if username == _username and password == _password: # 用户名与密码是否正确 print("\033[35;1m-----Welcome-----\033[0m") status = True # 修改用户登录状态 else: print("Wrong username or password") if status is True: # 已登录 print("\033[35;1m-----用户已登录-----\033[0m") func(*args, **kwargs) # 允许进入相关板块 america() or henan() return inner # 返回内层函数名 def home(): print("---首页----") @auth # 给函数加上装饰器,相当于执行:auth(america) ,稍后auth 会将函数inner返回,即america=inner def america(n): # 传递参数 print(n) print("----欧美专区----") def japan(): print("----日韩专区----") @auth # 给函数加上装饰器 def henan(): print("----河南专区----") home() america("付费啦,可以看美剧啦!!!") # 此时的america已经被“偷梁换柱”,相当于inner() japan() henan() # inner() 输出: ---首页---- username:qwe password:123 -----Welcome----- -----用户已登录----- 付费啦,可以看美剧啦!!! ----欧美专区---- ----日韩专区---- -----用户已登录----- ----河南专区----
但是,老板又提新需求了,要求"america"板块用“QQ”认证,"henan"板块用“WeChat”认证,其实就是在装饰器外面再加一层函数:
status = False # 用于判断用户登录状态 def outer(auth_login): def auth(func): # 将函数作为参数传入 def inner(*args, **kwargs): if auth_login == "QQ" or auth_login == "WeChat": global status # 定义全局变量 _username = "qwe" # 假设这是数据库用户信息 _password = "123" if status is False: # 未登录 username = input("username:") password = input("password:") if username == _username and password == _password: # 用户名与密码是否正确 print("\033[35;1m-----Welcome-----\033[0m") status = True # 修改用户登录状态 else: print("Wrong username or password") if status is True: # 已登录 print("\033[35;1m-----用户已登录-----\033[0m") func(*args, **kwargs) # 允许进入相关板块 america() or henan() else: print("Wrong authentication login:", func) # 认证方式错误提示 return inner # 返回内层函数名 return auth def home(): print("---首页----") @outer("QQ") # 带参数的装饰器 def america(n): # 传递参数 print(n) print("----欧美专区----") def japan(): print("----日韩专区----") @outer("WeChat") # 带参数的装饰器 def henan(): print("----河南专区----") home() america("付费啦,可以看美剧啦!!!") japan() henan() # inner()
以上是关于python——装饰器的主要内容,如果未能解决你的问题,请参考以下文章