python学习之路(十)
继续九写,还是装饰器
就是那个高阶函数:
def timer(func):
def deco(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
stop_time = time.time()
print('----------the func run time is %s' % (stop_time - start_time))
return deco
在 deco 函数里面 定义参数是不固定的 *args 和 **kwargs
然后在调用 func 的时候使用这些不固定的参数
然后继续往下走
上面那种装饰器 它已经可以满足日常 90% 的需求了
那现在再考虑一种情况:就是公司有网站 网站有好多的页面
假设一个页面就是一个函数 之前呢 是谁都可以看 没有任何的验证
现在不一样了 改了 不是随便谁都能看了 要加限制了
一百个页面里面 有二十个页面 不是随便看的 需要登录才能看
所以 就是说 一百个页面里面的二十个 需要加上验证功能
def index():
print('----------welcome to index page----------')
def home():
print('----------i am home-page----------')
def bbs():
print('----------i am bbs page----------')
这就是三个页面 index 页面不需要登录就可以看
而 home 页面 和 bbs 页面 是必须先登录 才能看到的
因为要加装饰器 所以先写上
def index():
print('----------welcome to index page----------')
@auth
def home():
print('----------i am home-page----------')
@auth
def bbs():
print('----------i am bbs page----------')
装饰器还没有实现 但是先写上
9.4 然后装饰器它肯定是一个高阶
def auth(func):
def wrapper(*args, **kwargs):
username = input('username:').strip()
password = input('password:').strip()
if username == user and password == passwd:
print('----------this is a Mr.Right----------')
func(*args, **kwargs)
else:
exit('----------sorry this is not a Right Man-----------')
return wrapper
看下它的运行效果:
9.5 来看下 home 函数的定义
@auth
def home():
print('\n----------i am home-page----------')
在这个定义里面 并没有返回值 可以给它加上返回值 并打印出来
所以定义改成这样:
@auth
def home():
print('\n----------i am home-page----------')
return 'return from home'
调用改成这样:print(home())
这个就是打印 home 函数的返回值的意思
来看下它的运行效果:
返回的是 None —— 为什么没有返回 return from home 呢
怀疑是装饰器改变了函数的结果 那怎么验证呢
—— 把装饰器暂时注释掉
所以装饰器 它虽然不改变原来函数的代码 也不改变原来函数的调用方式
但是 它改变了原来函数的执行结果 这个函数本来有结果
加上装饰器之后 结果没了 。。。
那么 应该怎样获得函数的结果呢
首先 加了装饰器之后 调用 home 实际上是在调用 wrapper
所以说 如果要得到 home 的结果 应该在 wrapper 函数里面去取得
def auth(func):
def wrapper(*args, **kwargs):
username = input('username:').strip()
password = input('password:').strip()
if username == user and password == passwd:
print('----------this is a Mr.Right----------')
res = func(*args, **kwargs)
print('----------after check username & password----------')
return res
else:
exit('----------sorry this is not a Right Man-----------')
return wrapper
来看下运行结果:现在是在本地做认证 但更好的应该是远程认证
意思就是 现在 用户名密码是保存在本地的
远程认证的话 就是把用户名密码保存在远程的某台服务器上
但是 重点不是具体的认证方式 重点是 认证方式可以不止一种 有很多种
在上面这个代码里面 它现在只能支持一种 就是把用户名密码保存在本地
而且现在 home 在进行认证的时候 它用的是本地认证
同时 bbs 在认证的时候 它用的也是本地认证
所以 可不可以改成 home 使用本地认证 而 bbs 使用远程认证呢?
那就是这样子:
就用这个参数 来区分本地认证 和远程认证
那这样子 就意味着 又要多传一个参数了 那怎么传呢?
给装饰器 再加一层 对 再加一层
那为了辨别各层的参数传的都是啥 需要多几个打印语句
# -*- coding:utf-8 -*-
# Author:Lucia Han
user, passwd = 'lucia', 'abc123'
def auth(auth_type):
print('auth_type:', auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print('wrapper_args and wrapper_kwargs is:', *args, **kwargs)
if auth_type == 'local':
username = input('username:').strip()
password = input('password:').strip()
if username == user and password == passwd:
print('----------this is a Mr.Right----------')
# res = func(*args, **kwargs)
func(*args, **kwargs)
# print('----------after check username & password----------')
# return res
else:
exit('----------sorry this is not a Right Man-----------')
elif auth_type == 'ladp':
print('搞毛线 ladp,不会。。。。。')
return wrapper
return outer_wrapper
def index():
print('\n----------welcome to index page----------\n')
@auth(auth_type = 'local')
def home():
print('----------so i am home-page----------\n')
# return 'return from home'
@auth(auth_type = 'ldap')
def bbs():
print('----------so i am bbs page----------\n')
index()
home()
# print(home())
bbs()
ok 那现在运行一下 看看效果: