1、装饰器定义:
装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。
2、装饰器的意义:
装饰器的作用就是为已经存在的对象添加额外的功能。并且同时取出与函数功能不符的代码到装饰器中使之得到重用。
3、先来看一个最简单的例子
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
user_statues = False # vip用户登陆后改为True
def login(func):
def inner():
_user = 'cc' #假设调用了数据库
_password = 's,123'
global user_statues #声明全局变量
if user_statues == False:
user = input('用户名:')
password = input('密码:')
if _user == user and _password== password:
print('welcome %s login'%user)
user_statues = True
else:
print('Invalid user or password...')
else:
print('You haved allready login!')
if user_statues:
func() # 验证通过了就调用相应功能
return inner #用户调用login时,只会返回inner的内存地址,下次调用时再加上()才会执行inner函数
def home():
print('-----首页-----')
def China():
print('----中国----')
def foreign():
print('----外国----')
China = login(China) # china = login(China) ,login调用被修饰函数的函数名(China)作为参数,然后再将返回值赋给被修饰函数(China)
foreign = login(foreign)
China() # 用户调用
foreign() # 用户调用
注意:
软件的开放-封闭原则
封闭:已实现的功能代码不应该被修改
开放:对现有功能的扩展开放
可以看出装饰器就是功能扩展专生的一般,专治各种不服,我既未修改原本的China函数,foreign()函数,又实现了认证登录。
China = login(China)可以替换为 @login,@login要发挥作用就得写在紧贴所修饰的函数上方。
4、装饰器进阶版
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#传参数普通版
user_status = False
def login(func):
def inner(*args,**kwargs):
_user = 'sc'
_pwd = 's,514'
global user_status
if user_status == False:
user = input('用户名:')
pwd = input('密码:')
if _user == user and _pwd== pwd:
print('Welocome %s login!'%user)
user_status = True
else:
print('Invalid username or password...')
else:
print('Ypu haved already login!')
if user_status:
func(*args,**kwargs) #无论是否传参都行
return inner
def home():
print('-------首页---------')
@login #jp = login(jp)
def jp(name):
print('------日本专区------',name)
home()
jp('宫崎骏')
5、装饰器高阶版
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#微信、QQ升级版传参
user_status = False
def login(auth_type): #QQ或微信登陆
def outer(func): # jp
def inner(*args,**kwargs):#’宫崎骏‘
_user = 'sc'
_pwd = 's,514'
global user_status
if user_status == False:
user = input('用户名:')
pwd = input('密码:')
if _user == user and _pwd== pwd:
print('Welocome %s login!'%user)
user_status = True
else:
print('Invalid username or password...')
else:
print('Ypu haved already login!')
if user_status:
func(*args,**kwargs) #无论是否传参都行
return inner
return outer
def home():
print('-------首页---------')
@login('qq') # xx = login('qq')=outer @outer= outer(jp)=inner
def jp(name):
print('------日本专区------',name)
@login('weixin')
def americ():
print('------美国专区-------')
jp('宫崎骏')
注意: @login('qq') 实际上可拆分为两部分@ 和 login('qq'),分两步,第一步,将’qq‘作为login的参数传入,
返回outer,此时@outer再将紧接后面的函数名(jp)作为outer的参数传入,返回inner给用户调用的方法即jp('宫崎骏'),
符合条件后跳转到相关函数功能执行功能。