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

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

一.什么是装饰器

顾名思义,装饰器指为其他函数添加新功能

装饰器定义:本质就是函数,功能是为其他函数添加新功能

 

二.装饰器需要遵循的原则

1.不修改被装饰函数的源代码(开放封闭原则)

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

3.装饰器的本质 :闭包函数

功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能

 

示例1:

import timedef timmer(func):    #函数名可以当做函数的参数    def inner():        start = time.time()        func()        end = time.time()        print(end - start)    return innerdef hahaha():    time.sleep(0.1)    print('aaaa')

示例2:

def timmer(func):  #---> hahaha    def inner(x,y):        func(x,y)  # --->hahaha    return innerdef hahaha(a,b):    time.sleep(0.1)    print(a,b)def kkk(a):    print(a)

三.装饰器的主要功能和装饰器的固定结构

装饰器的主要功能:

在不改变函数调用方式的基础上在函数的前、后添加功能。

装饰器的固定格式:

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

语法糖

import timedef wrapper(func):  # 装饰    def inner(*args, **kwargs):        start = time.time()        ret = func(*args, **kwargs)        end = time.time()        print(end - start)        return ret    return inner@wrapperdef lll():    time.sleep(0.1)    print('hello')lll()

 四.

  1.带参数的装饰器

def outer(flag):    def timer(func):        def inner(*args,**kwargs):            if flag:                print('''执行函数之前要做的''')            re = func(*args,**kwargs)            if flag:                print('''执行函数之后要做的''')            return re        return inner    return timer@outer(False)def func():    print(111)func()
View Code
F = Falsedef outer(flag):    def wrapper(func):        def inner(*args,**kwargs):            if flag:                print('before')                ret = func(*args,**kwargs)                print('after')            else:                ret = func(*args, **kwargs)            return ret        return inner    return wrapper@outer(F)  #-->@wrapper  -->hahaha = wrapper(hahaha)  #-->hahaha == innerdef hahaha():    print('hahaha')@outer(F)   #shuangww = outer(shuangww)def shuangww():    print('shuangwaiwai')shuangww()hahaha()
View Code

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

def qqxing(func):  #func = pipixia_inner    def qqxing_inner(*args,**kwargs):        print('in qqxing:before')        ret = func(*args,**kwargs)  #pipixia_inner        print('in qqxing:after')        return ret    return qqxing_innerdef pipixia(func):  #dapangxie    def pipixia_inner(*args,**kwargs):        print('in pipixia:before')        ret = func(*args,**kwargs)      #dapangxie        print('in pipixia:after')        return ret    return pipixia_inner#qqxing(pipixia_inner)  -->dapangxie = qqxing_inner()@qqxing    #dapangxie = qqxing(dapangxie)  -->dapangxie = qqxing(pipixia(dapangxie)) -->@pipixia   #dapangxie = pipixia(dapangxie)def dapangxie():    print("饿了么")dapangxie()
View Code

 3.开放封闭原则

(1)对扩展是开放的

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

(2)对修改是封闭的

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

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

练习:

'''编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码注意:从文件中读出字符串形式的字典,可以用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/shaojiafeng/p/7245423.html

你可能感兴趣的文章
云服务鼻祖来告诉你99%的创业者不知道的事
查看>>
WFA发布LTE-U共存测试计划 Wi-Fi和LTE-U将公平共享频谱
查看>>
快递单信息泄露惊人 隐形面单能拯救你的隐私吗?
查看>>
移动“村务云”创新“互联网+无线政务”新方式
查看>>
大数据企业落户山西将获重金奖励
查看>>
新品、新投资方两大悬念待解 海云捷迅发布会受关注
查看>>
Kubuntu 15.10 高清截图欣赏
查看>>
30 岁: 程序员心中永远的痛?
查看>>
《C++ 黑客编程揭秘与防范(第2版)》—第6章6.7节打造一个密码显示器
查看>>
时间到底是怎么弯曲的?
查看>>
《游戏编程模式》一1.7 准备出发
查看>>
讨喜的隔离可变性(十二)基于角色模型的局限性和小结
查看>>
《Nmap渗透测试指南》—第10章10.2节Zenmap基本配置
查看>>
《C语言点滴》一导读
查看>>
机器人系统设计与制作:Python语言实现3.2 习题
查看>>
《趣学JavaScript——教孩子学编程》——2.2 变量
查看>>
《SQL学习指南(第2版)(修订版)》——1.2 什么是SQL
查看>>
windows无法访问vmware搭建好虚拟机linux web服务器
查看>>
空中网多线程面试题
查看>>
python __setattr__, __getattr__, __delattr__, __call__
查看>>