闭包函数

一、什么是闭包

闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。简单的说闭包函数就是把变量和函数一起包起来,下次要用直接使用

def outter(x):def inner():print(x)return innerinner = outter(2)  # inner  # f = innerinner()inner()inner()
# 查看闭包的元素
print(F"f.__closure__[0].cell_contents: {f.__closure__[0].cell_contents}")

结果:
2
2
2
f.__closure__[0].cell_contents: 2

二、闭包函数的应用

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

应用领域:延迟计算(原来我们是传参的,现在我们包裹起来)、怕成领域

import requestsdef get(url):response = requests.get(url)print(f"done: {url}")get('https://www.baidu.com')
get('https://www.baidu.com')
get('https://www.baidu.com')get('https://www.cnblogs.com/linhaifeng')
get('https://www.cnblogs.com/linhaifeng')
get('https://www.cnblogs.com/linhaifeng')

one: https://www.baidu.com
done: https://www.baidu.com
done: https://www.baidu.com
done: https://www.cnblogs.com/linhaifeng
done: https://www.cnblogs.com/linhaifeng
done: https://www.cnblogs.com/linhaifeng

上面的方式是极其复杂的,我们如果使用默认参数也只能解决一个网址,因此我们可以考虑使用闭包的方式。

def func(url):def get_url():r = requests.get(url)r.raise_for_status()r.encoding = r.apparent_encodingprint(f'{url})# print(r.text[:1000])return get_urlget_baidu = func("https://www.baidu.com/")get_baidu()
get_baidu()get_taobao = func('https://www.taobao.com/')
get_taobao()
get_taobao()
get_taobao()print(get_taobao.__closure__[0].cell_contents)

结果:
url:https://www.baidu.com/
url:https://www.baidu.com/
url:https://www.taobao.com/
url:https://www.taobao.com/
url:https://www.taobao.com/
get_taobao.__closure__[0].cell_contentshttps://www.taobao.com/

装饰器

一、无参装饰器

1.1 什么是装饰器?

装饰器,器指的是工具,二而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象(函数)添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能

装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B,

需要注意的是:

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

  • 被装饰的对象也可以是任意可调用的对象

    def A():"""装饰器"""passdef B():"""被装饰的对象"""passB()

1.2 为什么要用装饰器?

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

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

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

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

1.3 如何使用装饰器

def index():"""被装饰的函数"""print('hello, index')index()

对上面函数实现:

  1. 打印函数运行的时

    1.1 改变了函数体代码,没改变调用方式

    import time
    def index():start = time.time()print("hello, index")time.sleep(1)end = time.time()print(end - start)
    index()

    1.2 没改变调用方式,也没改变源码,但是不通用

    import time
    def index():print("hello, index")start = time.time()
    index()
    time.sleep(1)
    end = time.time()print(end - start)
  2. 装饰器

检测index的运行的时间,但是不能改变index的调用方式,以及index的源码

def deco(func): # func = 真正的index"""装饰器函数"""def inner():start = time.time()func() # 真正的index()time.sleep(1)end = time.time()print(ent - start)return innerdef index():"""被装饰的函数"""print("hello, index")# 实现index函数调用
index = deco(index) # index = inner
index() # f1()

二、装饰器语法糖

在被装饰函数正上方,并且是单独一行写上@装饰器名

def deco(func): # func = 真正的index"""装饰器函数"""def inner():start = time.time()func() # 真正的index()time.sleep(1)end = time.time()print(ent - start)return innerdef index():"""被装饰的函数"""print("hello, index")
@deco
index() 

三、装饰器模板

def outter(func):def inner(*args, **kwagrs):res = func(*args, **kwagrs)return resreturn inner
def deco(func):"""装饰器"""def inner(*args, **kwargs): # inner是未来要运行的函数res = func(*args, **kwargs) # func实际调用的函数return resreturn inner@deco
def index(x, a=12):"""被装饰的对象"""print('x:',x,)print("a:", a)print('hello index')return indexres = index()
print(res)

实现一个用户登录装饰器。

def login(func):def ingfunc(*args, **kwargs):username = input("请输入用户名:")userpwd = input("请输入密码:")if username == 'randy' and userpwd:print("登录成功")res = func(*args, **kwargs)else:print('失败')return resreturn ingfunc@login
def shopping():print('shoppoing')shopping()

四、三层装饰器

# 三层装饰器
def sanceng(engine):def outter(func):def wrapper(*args, **kwargs):# 加功能print(engine)res = func(*args, **kwargs) # func被装的函数return resreturn wrapperreturn outter@sanceng('file')
def shopping()print("shopping")
# 判断账号密码来自于哪个地方
#三层装饰器: 给双层装饰器加参数
def auth(engine):def login(func):def inner(*args, **kwargs):# 登录功能if engine == 'file':username = input('usrename:')pwd = input('pwd:')if username == 'nick' and pwd == '123':print('登录成功')res = func(*args, **kwargs)  # shopping()                    return reselse:print('登录失败')elif engine == 'db':print('账号密码来自于数据库,非法请求')return innerreturn login@auth('db')
def shopping():print('shopping')login = auth('db')  # login = login
shopping = login(shopping)  # shopping = inner
shopping() # inner()
# 叠加多个装饰器
# 1. 加载顺序(outter函数的调用顺序):自下而上
# 2. 执行顺序(wrapper函数的执行顺序):自上而下

迭代器

一、迭代器的概念

迭代器即迭代的工具,那什么是迭代呢?
迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

while True: #只是单纯地重复,因而不是迭代print('===>') l=[1,2,3]
count=0
while count < len(l): #迭代print(l[count])count+=1

二、可迭代对象

python中一切皆对象,对于这一切的对象中,但凡有__iter__方法的对象,都是可迭代对象。

基于上一次的结果推出下一次结果

# # 可迭代(具有__iter__方法)对象x = 2  # 不可迭代
# x.__iter__  # SyntaxError: invalid syntaxs = 'randysun'
s.__iter__()  # str 为可迭代对象lt = [1, 2, 3]
lt.__iter__()  # list 为可迭代对象dic = {'a': 1, "b": 2}
dic.__iter__()  # dict 为可迭代对象tup = (1,)
tup.__iter__()  # tuple 为可迭代对象se = {1, 2, 3}
se.__iter__()  # 可迭代对象f = open('test.py')
f.__iter__()  # 可迭代对象def func():pass     # 不可迭代对象# 有__iter__()方法的对象都是可迭代对象,然后除了数字类型和函数之外都是可迭代对象

可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象。

s = 'randysun's_iter = s.__iter__()
print(s_iter.__next__())
print(s_iter.__next__())
print(s_iter.__next__())

特点:

  1. 内置有__iter__方法的都叫可迭代的对象。

二、迭代器对象

迭代器对象: 具有__iter__以及__next__方法的叫做迭代器对象

s = 'nick'  # 可迭代对象,不属于迭代器对象
s.__iter__()
lt = [1, 2, 3]  # 可迭代对象,不属于迭代器对象
dic = {'a': 1, 'b': 2}  # 可迭代对象,不属于迭代器对象
tup = (1,)  # 元组只有一个元素必须得加逗号# 可迭代对象,不属于迭代器对象
se = {1, 2, 3}  # 可迭代对象,不属于迭代器对象
f = open('time.py')  # 可迭代对象,迭代器对象# 只有文件是迭代器对象
lt = [1, 2, 3]
lt_iter = lt.__iter__()
while True:try:print(lt_iter.__next__())except StopIteration:break

1
2
3

for i in lt:  # 可迭代对象;迭代器对象 不依赖索引取值,而是迭代取值print(i)
# 1. 首先使用iter把it变成迭代器对象,对文文件也要使用iter方法把文件再一次iter
# 2. 然后使用next方法进行迭代取值
# 3. 判断StopIteration异常,遇到异常终止
  • 可迭代对象:具有__iter__方法的对象就是可迭代对象,除了数字类型和函数都是可迭代对象
  • 可迭代器对象:具有__iter__和__next__方法的都是迭代器对象,只有文件
  • 迭代器对象一定是可迭代对象,可迭代对象不一定是可迭代器对象
  • for循环 == 迭代循环
    1. 把lt(可迭代对象/迭代器对象)用__iter__方法转换成迭代器对象
    2. 使用__next__取出迭代器里的所有值
    3. 使用__next__方法取尽迭代器中的所有值,一定会报错,通过异常捕捉退出while循环
    4. 解决了不依赖索引取值
  • 优缺点
  1. 优点:

    • 提供一种统一的、不依赖于索引的迭代方式
    • 惰性计算,节省内存
  2. 缺点:
    • 无法获取长度(只有在next完毕才知道到底有几个值)
    • 一次性的,只能往后走,不能往前退

转载于:https://www.cnblogs.com/xiongchao0823/p/11342931.html

闭包函数 装饰器 迭代器相关推荐

  1. CHAR.VI 函数装饰器和闭包

    CHAR.VI 函数装饰器和闭包 函数装饰器用于在源码中"标记"函数,以某种方式增强函数的行为.这是一项强大的功能,但是若想掌握,必须理解闭包. nonlocal 是新近出现的保留 ...

  2. python 如何判断一个函数执行完成_Python核心编程的四大神兽迭代器、生成器 、闭包以及装饰器...

    本文将主要分为4大部分,分别介绍Python核心编程中的迭代器.生成器 .闭包以及装饰器. 生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yiel ...

  3. Python基础知识——函数的基本使用、函数的参数、名称空间与作用域、函数对象与闭包、 装饰器、迭代器、生成器与yield、函数递归、面向过程与函数式(map、reduce、filter)

    文章目录 1 函数的基本使用 一 引入 二 定义函数 三 调用函数与函数返回值 2 函数的参数 一 形参与实参介绍 二 形参与实参的具体使用 2.1 位置参数 2.2 关键字参数 2.3 默认参数 2 ...

  4. python四大器_Python编程四大神兽:迭代器、生成器、闭包和装饰器

    生成器 生成器是生成一个值的特殊函数,它具有这样一个特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序 ...

  5. python的装饰器迭代器与生成器_详解python中的生成器、迭代器、闭包、装饰器

    迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 1|1可迭代对象 以直接作用于 for ...

  6. python 函数修饰器 父类_Python函数嵌套、回调函数、闭包、装饰器和类

    markdown内容:Python函数嵌套.回调函数.闭包.装饰器和类 一级标题:主要描述内容 二级标题:各个内容 三级标题:重要概念 一.函数嵌套 1.1.作用域和嵌套函数 LEGB查找规则的 E, ...

  7. day4 高阶函数 嵌套函数 装饰器 内置函数 列表生成式 迭代器 生成器

    一.函数即变量 1.赋值效果图 a = 1  b = a def func(): print('hello') func 是函数名,相当于变量名,print('hello')是函数体,相当于变量的值, ...

  8. Python核心编程的四大神兽迭代器、生成器 、闭包以及装饰器

    本文将主要分为4大部分,分别介绍Python核心编程中的迭代器.生成器 .闭包以及装饰器. 生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yiel ...

  9. [python 进阶] 第7章 函数装饰器和闭包

    文章目录 7.1 装饰器基础知识 7.2 Python何时执行装饰器 7.3 使用装饰器改进"策略" 7.4 变量作用域(global) 备注 -比较字节码(暂略) 7.5 闭包 ...

最新文章

  1. 【Spring框架家族】mybatis generator代码自动生成(看得上眼直接拿去用即可)
  2. STM32应用实例六:与MS5837压力传感器的I2C通讯
  3. 【STM32】GPIO概述
  4. java并行计算同步返回_Java大文本并行计算实现过程解析
  5. 遍历结构体_三菱ST语言编程(3)——结构体变量
  6. mysql 千万数据分页_MySQL处理千万级数据查询、分页
  7. SpringMVC+idea+maven搭建项目
  8. VS Code 运行Vue项目
  9. python3 + pycharm+requests+HTMLTestRunner生成不了测试报告html
  10. SylixOS armv8 mmu
  11. cookie被淘汰_可爱可恨的 Cookie
  12. jquery ajax教程例子,jquery ajax教程例子
  13. 张家口地区某一级公路设计--河北建筑工程学院
  14. 【CNN】连续学习/持续学习,增量学习
  15. 单调队列优化dp--bzoj5185: [Usaco2018 Jan]Lifeguards
  16. bugku 我永远喜欢穹妹
  17. iOS开发画虚线的方法
  18. USACO修理牛棚 Barn Repair
  19. 在SQLServer处理中的一些问题及解决方法 NEWSEQUENTIALID()
  20. 试用matlab求e值,matlab中如何求e精确到20位

热门文章

  1. 后盾网lavarel视频项目---phpstorm 配置ftp, 自动更新同步代码
  2. 我看team work
  3. 区块链100问1-20问
  4. 正则表达式的学习二:正则表达式的匹配规则总结
  5. for语句之打印三角形问题
  6. 关于scrollTop为0以及解决方法
  7. 论项目团队情商与项目团队绩效(转)
  8. C语言-main方法的两个参数是干什么的?
  9. 《python核心编程第二版》第5章习题
  10. 关于渗透的一些思路持续更新(自我理解)