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

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

目录

闭包函数

什么是闭包

闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

def outter():    x = 1    def inner():        print(x)  # x = 1    return innerf = outter()  # f = innerdef f2():    x = 2    f()  # f() = inner()f2()
1

两种为函数传参的方式

方式一:使用参数的形式

def func(x):    print(x)func(1)
1

方式二:包给函数

def outter(x):    def inner():        print(x)    return innerf = outter(1)  # f = inner  ,x = 1print(f)f()
.inner at 0x0000017E2A641048>1

闭包函数的应用

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

应用领域:延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。

import requestsdef outter(url):    def get():        respond = requests.get(url)        print(f'done:{url}')    return getbaidu = outter('http://www.baidu.com')  # baidu = getbaidu()  # baidu() = get()taobao = outter('http://www.taobao.com')  # taobao = gettaobao()
done:http://www.baidu.comdone:http://www.taobao.com

装饰器

无参装饰器

什么是装饰器

器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。

注意:

  • 装饰器本身其实是可以任意调用的对象
  • 被装饰的对象也可以是任意可调用的对象

为什么要用装饰器

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方发法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

怎么用装饰器

# 改变调用方式import timedef index():    print('welcome to index')    time.sleep(1)def time_count(func):    start = time.time()    func()   # index()    end = time.time()    print(f'{func} time is {end - start}')time_count(index)   # 改变了index的调用方式
welcome to index
time is 1.0003917217254639
# 包给函数—外包import timedef index():    print('welcome to index')    time.sleep(1)def time_count(func):    def wrapper():        start = time.time()        func()  # index()        end = time.time()        print(f'{func} time is {end - start}')    return wrapperprint(index)  # 
print('*'*20)index = time_count(index) # index = wrapperindex() # index() = wrapper()print('*'*20)print(index) # 地址与第一个打印不同#
.wrapper at 0x0000017E2A8A00D0>
********************welcome to index
time is 1.0003859996795654********************
.wrapper at 0x0000017E2A8A00D0>

完善装饰器

  1. 如果原始的index()有调用值,上述的wrapper()却没有,两者的返回值应该相同,我们需要同步原始函数有个返回值。
import timedef index():    print('welcome to index')    time.sleep(1)    return "I'm index"def time_count(func):        def wrapper():        start = time.time()        res = func()  # res = index() = "I'm index"        end = time.time()        print(f'{func} time is {end - start}')                return res    return wrapperprint(index())print('*'*20)index = time_count(index)res = index()print(res)
welcome to indexI'm index********************welcome to index
time is 1.0053789615631104I'm index
  1. 如果原始的函数需要传参,那么我们之前的装饰器无法实现该功能的,那么只要给wrapper()传参即可。
import time def home(name):    print(f'welcome {name} to home page')    time.sleep(1)        return name    def time_count(func):        def wrapper(*args,**kwargs):                start = time.time()        res = func(*args,**kwargs)        end = time.time()        print(f'{func} time is {end - start}')                return res    return wrapperhome = time_count(home)  # home = wrapperres = home('william')  res = wrapper('william')print(res)
welcome william to home page
time is 1.0003857612609863william

装饰器语法糖

在被装饰的函数上方,单独写一行@装饰器名

# 上方函数用语法糖import time def time_count(func):        def wrapper(*args,**kwargs):                start = time.time()        res = func(*args,**kwargs)        end = time.time()        print(f'{func} time is {end - start}')                return res    return wrapper@time_countdef home(name):    print(f'welcome {name} to home page')    time.sleep(1)        return name@time_countdef index():    print('welcome to index')    time.sleep(1)    return "I'm index"        print(index())print('*'*20)print(home('william'))
welcome to index
time is 1.0003869533538818I'm index********************welcome william to home page
time is 1.0013864040374756william

装饰器模板

def deco(func):        def wrapper(*args,**kwargs):        res = func(*args,**kwargs)                return res    return wrapper

有参装饰器

无参装饰器只套了两层,下面是三层装饰器—有参装饰器。这个参数是装饰器的参数。

# 登陆注册(判断信息来源,'file'可以,其他不行)is_login_dict = {'username':None}def auth(origin):        def login(func):                def wrapper(*args,**kwargs):                        if origin == 'file':                print('from file')                                if not is_login_dict.get('username'):                    username = input('please enter your username>>>').strip()                    print('login successfully')                    res = func(*args,**kwargs)                    is_login_dict['username'] = username                    return res                else:                    res = func(*args,**kwargs)                    return res            else:                                print('illegal original')        return wrapper    return login@auth('file')def shopping():     print('from shopping')    @auth('mongodb')def withdraw():    print('from withdraw')    @auth('file')def paying():    print('from paying')            shopping()   # 需要输入用户名print('*'*20)withdraw()   #来源错误print('*'*20)paying()    # 无需再次输入用户名
from fileplease enter your username>>>williamlogin successfullyfrom shopping********************illegal original********************from filefrom paying

转载于:https://www.cnblogs.com/WilliamKong94/p/10961928.html

你可能感兴趣的文章
Unity调用Windows窗口句柄,选择文件和目录
查看>>
HashMap循环遍历方式
查看>>
React Native 入门 调试项目
查看>>
C# 通过 Quartz .NET 实现 schedule job 的处理
查看>>
关于java之socket输入流输出流可否放在不同的线程里进行处理
查看>>
目前为止用过的最好的Json互转工具类ConvertJson
查看>>
Day13
查看>>
tensorflow saver简介+Demo with linear-model
查看>>
Luogu_4103 [HEOI2014]大工程
查看>>
Oracle——SQL基础
查看>>
项目置顶随笔
查看>>
Redis的安装与使用
查看>>
P1970 花匠
查看>>
java语言与java技术
查看>>
NOIP2016提高A组五校联考2总结
查看>>
iOS 项目的编译速度提高
查看>>
table中checkbox选择多行
查看>>
Magento开发文档(三):Magento控制器
查看>>
性能调优攻略
查看>>
ie6解决png图片透明问题
查看>>