再谈装饰器@@@

装饰器
装饰器本质上就是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加
额外的功能,装饰器的返回值也是一个函数对象。
装饰器的使用场景:
1,日志插入
2,性能测试
3,事务处理(缓存、权限校验)
4,等。。。
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

最简单的装饰器:

def home_page():
print("This is the home_page")

def games_page():
print("This is the games_page")

def music_page():
print("This is the music page")

现在要求,在访问games_page与music_page的时候,要求进行用户登录,就需要对代码进行修改

方法1,
修改函数games_page、music_page,去添加登录功能

def games_page():
print("Login account ")
print("This is the games_page")

缺陷:
代码重复,每个子页面都需要添加登录代码
原函数已经完成了本质功能,不应该修改代码

方法2,
定义一个login函数,在子页内调用login函数
def login():
print("Login account")

def games_page():
login()
print("This is the games_page")

缺陷:
还是修改了原功能代码块,不够完美


方法3,
在不改变原代码块的基础上,重新声明子页
def login(arg):
print("Login account")
return arg()

def games_page():
print("This is the games_page")

games_page = login(games_page)

解析:
函数的return值,不指定的时候是none,
但是这里的login函数中,我们可以看到形参 arg,被return了,并且添加了(),就可以很明显的知道这个login需要传入函数参数,
”games_page = login(games_page)“的解析
把games_page 函数名作为参数传递给login()函数,就会首先运行login函数内的代码块,再把games_page作为返回值运行,这样就是
先运行了login()函数的功能,再运行了games_page()的功能。
其实这个本质就是装饰器!

装饰器的调用,通过在@实现,修改方法3,
def login(arg):
print("Login account")
return arg

@login
def games_page():
print("This is the games_page")


这样调用是有问题的,因为装饰器是自动运行的,所以我们没有调用函数games_page,函数login就已经运行了。


需要继续修改:
def login(arg):
def inner():
print("Login account")
return arg()
return inner

@login
def games_page():
print("This is the games_page")

games_page()

解析:
装饰器自动运行,但是只是返回了一个:
games_page = login(games_page)
login函数的返回值:inner
也就是说 games_page = inner
games_page() 等于运行函数 inner
函数inner内部操作就很明显了







原文地址:https://www.cnblogs.com/alben-cisco/p/6995716.html