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

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

装饰器

装饰器的主要功能:

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

装饰器的固定格式:

#装饰器的本质 :闭包函数#功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能def timmer(func):    def inner(*args,**kwargs):        '''添加函数调用之前的扩展代码'''        ret = func(*args,**kwargs)        '''添加函数调用之后的扩展代码'''        return ret    return inner

语法:在被装饰对象的正上方的单独一行,使用@语法糖可以直接调用函数装饰器

设计模式

原则 开放封闭原则

#对扩展是开放的

#对修改是封闭的 

1.对扩展是开放的

    为什么要对扩展开放呢? 

    我们必须允许代码扩展、添加新功能。

2.对修改是封闭的 

    为什么要对修改封闭呢? 

    我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

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

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()

 

编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
login_dic={"name":"None","passwd":"None", }with open('passwd.txt', 'r+', encoding='utf-8') as f1:    f2 = eval(f1.read())def login(func):    def inner(*args, **kwargs):        '''判断用户名、密码是否在字典中'''        if login_dic["name"]==f2["name"] and login_dic["passwd"]==f2["passwd"]:            ret = func(*args, **kwargs)            return ret        else:            name = input("请输入用户名:")            passwd = input("请输入密码:")            if name == f2['name'] and passwd == f2['passwd']:                print("登陆成功")                login_dic['name'] = name                login_dic['passwd'] = passwd                ret = func(*args, **kwargs)                return ret            else:                print("输入有误,请重新输入")    return inner@logindef fun():    print("123")    print("456")fun()@logindef check():    print("789")

 带参数的装饰器

def timer(func):    def inner(a):        start = time.time()        func(a)        print(time.time() - start)    return inner@timerdef func1(a):    print(a)func1(1)装饰器——带参数的装饰器
import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        print(time.time() - start)        return re    return inner@timer   #==> func1 = timer(func1)def func1(a,b):    print('in func1')@timer   #==> func2 = timer(func2)def func2(a):    print('in func2 and get a:%s'%(a))    return 'fun2 over'func1('aaaaaa','bbbbbb')print(func2('aaaaaa'))装饰器——成功hold住所有函数传参
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'))装饰器——带返回值的装饰器
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()带参数的装饰器格式
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()多个装饰器装饰同一个函数

实例

#带参数的装饰器 开关# F = TrueF = 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()
'''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'))print(get('http://www.cnblogs.com/linhaifeng'))print(get('http://www.cnblogs.com/linhaifeng'))print(get('http://www.cnblogs.com/linhaifeng'))print(get('http://www.cnblogs.com/linhaifeng'))

 

转载于:https://www.cnblogs.com/zhangningyang/p/7245315.html

你可能感兴趣的文章
分块学习
查看>>
UIWebView 屏蔽或者修改 alert警告框
查看>>
Qt-第一个QML程序-3-自定义一个按钮
查看>>
分布式系统事务一致性解决方案
查看>>
树梅派中文输入法支持
查看>>
[Git] 005 初识 Git 与 GitHub 之分支
查看>>
使用Analyze 和Instruments-Leaks分析解决iOS内存泄露
查看>>
Vue.js的入门
查看>>
【自定义异常】
查看>>
pip install 后 importError no module named "*"
查看>>
一些疑惑
查看>>
Codeforces Round #413 A. Carrot Cakes
查看>>
Linux(Ubuntu16.04)下添加新用户
查看>>
Windows c++应用程序通用日志组件(组件及测试程序下载)
查看>>
openstack dpdk
查看>>
springmvc跳转方式
查看>>
Linux安装Redis
查看>>
IOS 第三方管理库管理 CocoaPods
查看>>
背景色渐变(兼容各浏览器)
查看>>
Redis中7种集合类型应用场景
查看>>