1Python基础-装饰器-推导式-生成器-迭代器-可迭代对象-全栈式开发13

一、装饰器

(一)装饰器的引入

  • 我们想为函数添加更多功能,如果直接在原来的基础上修改,会出现以下问题:
    • 如果修改的函数多,修改起来会比较麻烦
    • 不方便后期的维护
    • 这样做会违反开闭原则(ocp–open close prinsaple)
      ocp原则:程序的设计,要求开发对程序的扩展,要关闭对程序的修改,开放对代码的扩展,关闭代码的修改
  • 如果之前引用过,那么你直接改掉会影响很大,所以我们最好是对函数扩展

(二)装饰器的作用

  • 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
  • 在开发中,我们都是通过装饰器来扩展函数的功能的

(三)装饰器的创建

  • 首先是闭包函数
  • 利用@调用
    原函数需要装饰器,但是我们调用的是原函数,加一个@原函数就加上了该设备,叫装饰器的语法糖@fun,相当于fun1(fun) ,就可以在原函数调用了
    在这里插入图片描述
    在这里插入图片描述
  • 过程解析:首先要调用函数,然后内层函数暂时不会执行,然后外层函数的调用=外层函数的返回值,然后外层函数的返回值是内层函数的函数对象,内层函数的调用等于内层函数的函数对象加一个括号,也就是调用,那么也就是外层函数的调用加上括号就是对内层函数的调用

二、推导式

(一)推导式的引入

  • 代码的可读性:使用for循环来实现相同的功能,需要好几行代码,而列表推导式只需要一行代码.
  • 在Python3中列表推导式有自己的局部作用域,就像函数似的.表达式内部的变量和赋值只在局部起作用,表达式的上下文里的同名变量还可以被正常引用,局部变量并不会影响到它们.

(二)推导式的定义

  • 推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体
  • 代码超过了两行,就要考虑改成用for循环了

(三)推导式创建

  • python中有三种的推导式,它们分别为:列表推导式、字典推导式、集合(set)推导式

列表推导式

  • 变量名= [表达式 for 变量 in 可迭代对象 if 条件]
    • 可以嵌套for循环
      在这里插入图片描述

字典推导式

  • 变量名={v:k for v,k in 字典.items() if 条件语句}
    变量名={v:k for v,k in 双值子序列 if 条件语句}
    在这里插入图片描述

集合(set)推导式

  • 变量名={表达式 for 变量 in 可迭代对象}
    变量名= {表达式 for 变量 in 可迭代对象 if 条件}
    • 可迭代对象:range()、list、dict(只会存key)、string、tuple
    • 集合是无序且不重复的,所以会自动去掉重复的元素,并且每次运行显示的顺序不一样
      在这里插入图片描述

三、迭代器

(一)迭代器简介

定义

  • 可以被next()函数调用并不断返回下一个值的对象称为迭代器Iterator
  • 迭代器指的是迭代取值的工具,迭代是指一个重复的过程,每一次重复都是基于上一次的结果而来的

特点

  • 迭代提供了一种通用的不依赖索引的迭代取值方式
  • 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 永远返回的是自身
    在这里插入图片描述
    在这里插入图片描述
    迭代器与可迭代对象区别
  • 迭代器: 可以用next()作用的都是迭代器类型
    • 迭代器一定是可迭代对象
    • 生成器也是迭代器
  • 可迭代对象: 可以用for循环遍历的对象都是可迭代对象
    • str、list、tuple、dict、set、等都是可迭代对象,可以通过iter()函数将他们转为迭代器
    • python的for循环本质就是通过不断调用next()函数实现的
      判断是否是可迭代对象

(二)迭代器的创建

方法有两种:iter函数、类创建

iter()函数

  • 将可迭代的对象变成迭代器
    在这里插入图片描述

__iter__ 与 __next__类创建

  • 两个方法都有的话就是迭代器
    • _iter_()方法:
      • 返回一个特殊的迭代器对象,一定要return self
      • 有__iter__(),这里实例对象就是可迭代对象,再加__next__就是迭代器
    • _next_() 方法:
      • 返回下一个对象。并通过 StopIteration 异常标识迭代的完成(就是调用次数超过元素个数时报的异常)。
      • 如果没有__iter__(),next也可以返回下一个数字,但是这样产生的就不是迭代器,就用不了for循环
        在这里插入图片描述

(三)迭代器的使用

  • 直接调用不能将数显示出来,要借用next()
  • 迭代器对象可以结合常规for或while语句进行遍历

next()

  • next(iterator, default=None)
    • iterator:传入的必须是迭代器
    • 将迭代器调用出来
      在这里插入图片描述

四、生成器

(一) 生成器简介

引入

  • 通过列表推导式我们可以直接创建出一个列表,但是受到内存的限制,我们不可能创造出一个无限大的列表。而且创建一个有200万个元素的列表,会占用很大的内存空间,而这个时候我们仅仅需要访问列表中几个元素,那么后面的元素就占用着空间就是一种浪费的行为。
  • 那么我们可不可以用几个元素就创建出几个元素。这样在一定程度上就优化了内存。所以引入了生成器

生成器

  • 一边循环一边计算的机制就是生成器
  • 也是一种迭代器

特点

  • 会删掉已经执行的数据
  • 你取出去了这个数据,那么这个数据在生成器里面就不存在了,当你把生成器里的数据取完了,那么它就不能够继续使用了,也就是说生成器只能用一次

(二) 生成器的创建

两种方法:类似列表推导式、利用yield

类似列表推导式

  • 方法和列表推导式一样,只是把外符号换成()
    在这里插入图片描述

利用yield

yield定义

  • 只要在函数中出现yield关键字它就是一个生成器函数
  • 这个就是我们的这个yield关键字的效果,只要我们在函数中使用了yield关键字,那么它不在是一个函数,而是一个生成器

yield执行顺序

  • 第一调用的时候是到yield那行代码结束
  • 我们第二次调用的时候,并不是自上往下执行的,而是从上一次停止的位置继续执行的,这也就是我们的生成器的特性,它会记住你上一次停留的地方,下次继续从这个地方开始执行。
  • 到yield结束运行。那么这个原因还是和它变成了一个生成器的原因所导致的。生成器一样的会和input函数一样起一个类似的阻塞作用,需要你调用它内部的next方法才会使程序执行一次,当你再一次遇到yield的时候,同样又会停止
    在这里插入图片描述

yield生成器的返回值

  • 可以设置返回值
  • 返回值是当值取完的时候会返回的值

(三) 生成器的使用与关闭

  • 生成器的使用:next(迭代器) 、 生成器.send()
  • 生成器的关闭:生成器.close()

生成器.send()

  • res = 生成器.send(a)
    • a :
      • 第一次调用的生成器传进去的值必须是None,也可以用next先启用第一次
      • 可以传任意值,传的值是等于res
    • res= yield n
      print(res)
      • 就会打印上一次调用send括号里的值
        在这里插入图片描述

生成器.close()

  • close() 关闭后就不能调用next或send

验证生成器会删掉已经执行的数据

  • response = None这块,为什么会出现这么个结果,是不是有同学会纳闷,它的结果不应该是1吗?怎么会是None呢?这里我要告诉大家的是,这个1的结果已经被我们的yield返回出去了,所以这里没有数据,这也是生成器的另一个特征之一
    在这里插入图片描述

小练习

1.请使用装饰器实现已存在的函数的执行所花费的时间。

def fun1(fn):
    
    import time 
    def fun2():
        time1=time.time()
        fn()
        time2=time.time()
        print('函数所耗时为:%f'%(time2-time1))
    
    
    return fun2

@fun1
def fun():
    s=0
    for i in range(100000):
        pass
fun()

在这里插入图片描述

总结:

装饰器
为了给原来的函数扩展,不该原来的情况下

装饰器:
是一个闭包
用@加在原来的函数上

闭包的要求:

函数嵌套
嵌套的函数要用到外部函数的值
外部函数返回的是嵌套函数对象

高阶函数:
将函数作为返回值返回
接受函数作为参数

推导式
分为列表推导式、字典推导式、集合推导式
列表推导式:[i for i in range(6) if 条件语句]
字典推导式:{v:k for i in dict1.items() if 条件语句} 与 {v:k for i in 双值子序列 if 条件语句}
集合推导式:{i for i in range(6)if 条件语句} 会自动删去重复的

迭代器

可以被next引用的容器
创建:iter() 与__iter__和__next__结合
iter()只要是可迭代的数据类型都可以转化为迭代器,基本数据类型都可以应用
__iter__和__next__更像是创建了一个可以实现迭代的类,类实例化的每一个对象都是迭代器
__iter__将对象变成可迭代的对象,实现__next__就是迭代器
__iter__返回下一个的,可以在这里添加判断,抛出异常
迭代器的调用
for

for i in 迭代器:
    print(i)

next(迭代器)
生成器.send(数字)
第一次调用的时候要么传None,要么先用next调用一下
生成器
引入
用几个就创建几个
创建
类似的列表推导式(i for i in range() if 条件语句)就是把列表推导式的[]换成()
yield 有yield的就是生成器

def fun():
    num    
    while True:  
        num+=1        
        yield num
        
a=fun()
next(a)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋芋本人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值