博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数之装饰器
阅读量:5332 次
发布时间:2019-06-14

本文共 4485 字,大约阅读时间需要 14 分钟。

今天我们准备学习函数的装饰器,其中包括楔子,装饰器的形成过程和主要功能、装饰器的固定结构。

1.首先我们需要知道什么是装饰器?

     装饰器本质就是函数,为其他函数提供新功能。

2.装饰器需要遵循的原则:(1)不修改被装饰函数的源代码(开放封闭原则)

                                          (2)为被装饰函数添加新功能后,不修改被修饰函数的调用方法

 3.装饰器形成的过程和主要功能

   装饰器的本质:一个闭包函数

  (1)形成过程: 

import timedef func1():    print('in func1')def timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return innerfunc1 = timer(func1)func1()

  由于赋值调用步骤较多,需要用到语法糖,具体代码如下:

import timedef timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return inner@timer   #==> func1 = timer(func1)def func1():    print('in func1')func1()
装饰器——语法糖

    (2)装饰器的功能:在不修改原函数及其调用方式的情况下对原函数的功能进行扩展

    装饰器的固定格式 

def timer(func):    def inner(*args,**kwargs):        '''执行函数之前要做的'''        re = func(*args,**kwargs)        '''执行函数之后要做的'''        return re    return inner

  4.无参装饰器

def timmer():      def wrapper():            func()      return wrapper
无参装饰器之基本框架

  5.带参装饰器

def func(func):      def wrapper(*args,**rargs):             func(*args,**kargs)       return wrapper
View Code

加上功能

import timedef timer(func):     def  wrapper(*args,**kwargs):             start=time.time()             func(*args,**kwargs)             end=time.time       print('')
带功能的装饰器

 带返回值的装饰器

import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        print(time.time() - start)        return re    return inner@timer   #==> func2 = timer(func2)def func2(a):    print('in func2 and get a:%s'%(a))    return 'fun2 over'func2('aaaaaa','bbbbbb')print(func2('aaaaaa')) 装饰器—带返回值的装饰器
View Code

 6.开放封闭原则

(1)对扩展是开放的

我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

(2)对修改是封闭的

就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

 7.多个装饰器装饰同一个函数

  有些时候,我们也会用到多个装饰器装饰同一个函数的情况。

def wrapper1(func):    def inner():        print('wrapper1 ,before func')        func()        print('wrapper1 ,after func')    return innerdef wrapper2(func):    def inner():        print('wrapper2 ,before func')        func()        print('wrapper2 ,after func')    return inner@wrapper2@wrapper1def f():    print('in f')f()
多个装饰器装饰同一个函数

练习:

'''编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式'''# user_dict = {
# 'pang':'123456',# 'panda':'binbin',# 'nezha':'101010'# }# print(type(user_dic))auth_status = { 'user':None, #设置全局的字典 'status':False}def auth(func): def inner(*args,**kwargs): if auth_status['status']: #如果auth_status为真,直接调用就行 ret = func(*args, **kwargs) # index/home return ret else: username = input('username : ').strip()#.strip()避免用户输入带有空格的用户名 password = input('password : ').strip() # 读文件获取用户信息 f = open('conf') #文件句柄 user_info = f.read() #读取user用户信息 user_dic = eval(user_info) #通过eval转换成字典 if user_dic.get(username) and user_dic[username] == password:#获取字典的k,确认有存在的用户名并找到对应的密码 print('login successful') auth_status['user'] = username auth_status['status'] = True ret = func(*args,**kwargs) #index/home 如果登录成功执行func return ret else: print('login failed') return inner@auth #装饰器def index(): print("欢迎来到首页")@authdef home(): print("欢迎回家")index()index()home()index()# #认证功能# #获取用户名和密码# username = input('username : ').strip()# password = input('password : ').strip()# #读文件获取用户信息# f = open('conf')# user_info = f.read()# user_dic = eval(user_info)# if user_dic.get(username) and user_dic[username] == password:# print('login successful')# else:# print('login failed')

 

'''进阶作业(选做):1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果2.编写装饰器,实现缓存网页内容的功能:具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中'''url_l = []from urllib.request import urlopendef get_cache(func):    def inner(*args,**kwargs):        url = args[0]        filename = str(hash(url))        if url in url_l:            f = open(filename,'rb')            ret = f.read()        else:            url_l.append(url)            ret = func(*args, **kwargs)            f = open(filename,'wb')            f.write(ret)        f.close()        return ret    return inner@get_cachedef get(url):    return urlopen(url).read()print(get('http://www.cnblogs.com/linhaifeng'))

 

  

 

  

 

  

  

转载于:https://www.cnblogs.com/moning/p/7245373.html

你可能感兴趣的文章
asp.net MVC helper 和自定义函数@functions小结
查看>>
L1-Day34
查看>>
Linux主机在LNMP环境中同时运行多个PHP版本
查看>>
玩转Xcode之修改系统生成的注释模板
查看>>
8、二进制中1的个数------------>剑指offer系列
查看>>
.eww
查看>>
ssh The authenticity of host '10.11.26.2 (10.11.26.2)' can't be established
查看>>
代码学习总结
查看>>
初入Installshield2015
查看>>
vs2010 无法创建 *.edmx(Entity Frame Work) 文件的问题
查看>>
<C++>查询
查看>>
2019-07-29 CentOS安装
查看>>
Leetcode-944 Delete Columns to Make Sorted(删除列以使之有序)
查看>>
P1087-FBI树
查看>>
怎么在某个控制器中判断程序是否在前台或后台
查看>>
第三周vim入门学习1
查看>>
Linux内核分析(第九周)
查看>>
Serlvet学习笔记之一 ——实现servlet的3种方法
查看>>
批处理
查看>>
使用pycharm编写自动化脚本
查看>>