Python中的三器一闭(详细版)

2023-11-17

迭代器

什么是迭代

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

在python中,迭代是访问集合元素的一种方式。对list、tuple、str等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。

什么是可迭代对象

一个对象如果实现了__iter__方法(魔法方法),那么我们称这个对象是可迭代对象。

或者可以这样理解,只要是可以通过for…in…的形式进行遍历的,那么这个数据类型就是可以迭代的。

判断数据是否可迭代

python中要判断一个对象是否是可迭代的,可以用collections模块中的Iterable来进行判断。isinstance函数会返回True或False来表明对象是(True)或者不是(False)可迭代对象。

from collections.abc import Iterable

print(isinstance(["abc"], Iterable))
print(isinstance([100], Iterable))


在这里插入图片描述

什么是迭代器

迭代器的作用是用来访问容器(用来保存元素的数据结构)中的元素,所以使用迭代器,我们就可以访问容器中里面的元素。

迭代器是一个可以记住遍历的位置的对象。迭代器对象从第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器的本质

我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。

使用迭代器取数据

from collections.abc import Iterator

nums = [3, 6, 8]  # 可迭代对象
nums = iter(nums)  # 创建了迭代器
print("nums", isinstance(nums, Iterator))  # 判断是否是迭代器
# 取出迭代器的数据
num1 = next(nums)
print(num1)
num1 = next(nums)
print(num1)
num1 = next(nums)
print(num1)

在这里插入图片描述

若迭代的次数超过了可迭代对象的长度, 就会报StopIteration异常

自定义迭代器

使用__iter__和__next__方法自定义迭代器

只要在类中,定义__iter__方法,那么这个类创建出来的对象一定是可迭代对象

如果类中实现了__iter__方法和__next__方法的对象,就是迭代器。

当我们调用iter()函数提取一个可迭代对象的 迭代器时,实际上会自动调用这个对象的__iter__方法,并且这个方法返回迭代器。

# 使用迭代器完成学生管理系统
class StuSystem(object):
    """
    学生管理系统
    """
    def __init__(self):
        self.stus = []
        self.current_num = 0

    def add(self):
        """
        添加一个新的学生
        :return:
        """
        name = input("请输入新学生的姓名:")
        tel = input("请输入新学生的手机号:")
        address = input("请输入新学生的住址:")
        new_stu = dict()
        new_stu["name"] = name
        new_stu["tel"] = tel
        new_stu["address"] = address
        self.stus.append(new_stu)

    def __iter__(self):
        return self

    def __next__(self):
        if self.current_num < len(self.stus):
            ret = self.stus[self.current_num]
            self.current_num += 1
            return ret
        else:
            self.current_num = 0
            raise StopIteration

# 创建对象
stu = StuSystem()

# 添加信息
stu.add()
stu.add()
stu.add()

stus = [x for x in stu]

print(stus)

在这里插入图片描述

凡是可作用于for循环的对象都是Iterable 类型;
凡是可作用于 next() 函数的对象都是Iterator 类型;
集合数据类型如list 、dict、str等是 Iterable但不是Iterator,不过可以通过 iter()函数获得一个Iterator对象。

生成器

一边循环一边计算的机制,称为生成器(generator)

在Python中,使用了yield的函数被称为生成器。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。生成器函数一般是通过for循环调用,for循环自带next方法。

创建生产器的方法

1.将列表推导式的[]改为()
2.在函数中使用yield关键字,函数就变成了一个generator

使用生成器完成斐波那契数列

def fib_generator():
    num1 = 1
    num2 = 1
    while True:
        temp_num = num1
        num1, num2 = num2, num1+num2
        # return temp_num  # 方式1代码
        yield temp_num

# 方式1代码(方式1不能够生成1,1,2,3,5...斐波那契数列)
# print(fib_generator())
# print(fib_generator())
# print(fib_generator())
# print(fib_generator())

# 方式2代码(可以生成斐波那契数列)
fib = fib_generator()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

在这里插入图片描述

关键字yield

yield是一个类似return的关键字。当我们调用这个函数的时候并不是返回计算的结果。而是返回一个生成器。只有迭代这个生成器的时候才会计算结果。

next和send

next()方法:
在调用生成器运行的过程中,每次遇到 yield ,函数返回当前的值,并且会暂停并保存当前所有的运行信息, 并在下一次执行 next() 方法时从当前位置继续运行。

send()方法:
先理解个概念【休眠】:意思就是暂时保留先不进行,等待需要时再进行。作用与next()作用相似
区别:
1.send(value)可以传递value给yield,即:我们可以指定yield返回啥就返回啥,
2.next()不能传递特定的值,只能传递None进去。

def genterator_test():
    while True:
        print("--1-")
        num = yield 100
        print("--2--", "num=", num)


g = genterator_test()
print(g.send(None))
print(g.send(11))
print(g.send(22))

在这里插入图片描述

生成器的特点:
存储的是生成数据的方式(即算法),而不是存储生成的数据,因此节约内存。

装饰器

装饰器是给现有的模块增添新的小功能,可以对原函数进行功能扩展,而且还不需要修改原函数的内容,也不需要修改原函数的调用。

装饰器的功能

装饰器的实现是由闭包支撑的;
装饰器本质上是⼀个python函数,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能;
装饰器的返回值也是⼀个函数的对象,它经常用于有切面需求的场景,实现路由传参,flask的路由传参依赖于装饰器,浏览器通过url访问到装饰器的路由,从而访问视图函数获得返回的HTML页面;

定义装饰器

def check_login(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        func()

    return inner


@check_login
def f1():
    print('f1')

def check_login(func):
    def inner():
        # 验证1
        if "admin" != input("请输入用户名:"):
            return "用户名不正确"
        # 验证2
        if "123456" != input("请输入密码:"):
            return "密码不正确"
        # 验证3
        if "7788" != input("请输入手机短信验证码:"):
            return "验证码不正确"

        func()

    return inner


@check_login
def f1():
    print('f1')


f1()  # 调用f1函数

闭包

什么是闭包

如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

# 定义函数可以理解为:
# 定义了一个全局变量,其变量名字是函数的名字,即test
# 这个test变量指向了一个代码块,这个代码块是函数
# 其实就是说test保存了一个代码块的地址,即引用
def test():
    print("--- in test func----")

test()  # 这是调用函数

ret = test # 用另外一个变量 复制了 test这个引用,导致ret变量也指向那个 函数代码块

# 下面输出的2个地址信息是相同的
print(id(ret))
print(id(test))

# 通过引用调用函数
ret()

函数、匿名函数、闭包、对象 当做实参时的区别

匿名函数能够完成基本的简单功能,,,传递是这个函数的引用 只有功能
普通函数能够完成较为复杂的功能,,,传递是这个函数的引用 只有功能
闭包能够将较为复杂的功能,,,传递是这个闭包中的函数以及数据,因此传递是功能+数据
对象能够完成最为复杂的功能,,,传递是很多数据+很多功能,因此传递是功能+数据

悲索之人烈焰加身,堕落者不可饶恕。永恒燃烧的羽翼,带我脱离凡间的沉沦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python中的三器一闭(详细版) 的相关文章

随机推荐

  • [docker]搭建elasticsearch服务

    1 拉取镜像 docker pull elasticsearch 8 7 0 如果需要其他版本的话 访问 Dockerhttps hub docker com ela
  • QT从入门到入土(四)——文件的读写操作

    引言 文件的读写是很多应用程序具有的功能 甚至某些应用程序就是围绕着某一种格式文件的处理而开发的 所以文件读写是应用程序开发的一个基本功能 Qt 提供了两种读写纯文本文件的基本方法 用 QFile 类的 IODevice 读写功能直接进行读
  • uniapp中的分享功能实现(APP,小程序,公众号)

    uniapp中的分享功能实现 APP 小程序 公众号 1 APP端的分享 app端的分享可以直接使用uniapp封装的方法uni share uni app的App引擎已经封装了微信 QQ 微博的分享SDK 开发者可以直接调用相关功能 可以
  • Android交叉编译OpenCV+FFmpeg+x264的艰难历程

    前言 如果你没有兴趣看完本文 只想获得可编译的代码或编译后的产物 可以直接点击下面的链接 跟随步骤编译代码或直接下载我编译好的产物 注 编译顺序要按照 x264 gt FFmpeg gt OpenCV 这样来 x264 FFmpeg Ope
  • 使用less处理重复性background-image定位问题

    1 问题描述 使用angular的列表循环解释问题 其他框架类似 css上面使用flex布局 index html代码 div class container div class item div class div p class ite
  • CH3-HarmonyOS开发基础

    文章目录 背景 目标 一 APP 1 1 APP包组成 1 2 APP和HAP结构 二 Ability 2 1 Ability 2 2 pack info 三 libs库文件 3 1 HAR 四 resources资源文件 4 1 reso
  • shiro框架---关于用户登录退出接口的介绍

    接上一篇文章shiro框架 shiro配置用户名和密码的注意 项目已分享到GitHub上 如果需要的可以看下 springboot shiro项目Git下载地址 在我前几篇文章里有shiro配置的文件下载包 下载后里边有四个配置文件Shir
  • 618省心凑背后的新算法——个性化凑单商品打包购推荐

    作为购物导购链路的一个重要环节 凑单旨在快速帮助用户找到达成某个满减门槛 比如满300减50 的商品 完成性价比最高的跨店组合结算 前言 背景 凑单是一个历史悠久的场景 伴随着长期优化并不断升级 为用户决策提供了便捷通道 作为购物导购链路的
  • Nginx部署前端,并转发2个后台,实现负载均衡

    一 vue打包 cmd进入项目目录 执行 npm run build 会在改目录生成dist文件 假设dist目录是 D dist 二 部署 下载nginx 修改nginx conf 在http 中加入 upstream myapp1 se
  • 在SQL中直接使用存储过程查询返回的结果集

    在实际使用存储过程是 有时我们希望先判断存储过程的返回结果集是否有记录 然后走不同的业务逻辑 这是就需要在SQL语句中直接读取到存储过程的返回结果集 方式如下 先按照存储过程结果集定义一个变量 declare tbl table 门诊号 v
  • js预编译(与C预处理区别)

    目录 1 函数体内 例 2 全局 注 window 属性和 imply global属性 3 全局和函数体内结合 优先顺序 例1 例2 例3 重要提示 第一次学的时候以为和C预处理差不多 看了下才发现区别还蛮大的 例1 test 打印出 a
  • 说一下Photo服务器

    误打误撞学习了一下Photo服务器 自己去百度上找 有些问题大家也没说清楚 所以 在这里补充说明一下 现在Photo官网已经更新到4 0 29 说不定有更新了 但是很多教程都是Photo3 0的版本 虽然大体还是差不多 但是对于初学者来说还
  • mysql useunicode_jdbc连接mysql 为什么在连接时已经这样设置了 ?useUnicode=true&characterEncodin...

    jdbc连接mysql 为什么在连接时已经这样设置了 useUnicode true characterEncoding UTF 8 autoReconnect true maxReconnects 10 autoReconnectForP
  • Python 并发系列 2 —— 各种并发方案的选择

    目录 二 异步 Python 不同形式的并发 2 1 术语定义 同步 Sync vs 异步 Async 并发 Concurrency vs 并行 Parallelism 2 2 线程 Threads 进程 Processes Threads
  • Nginx代理规则总结

    Nginx代理规则总结 说明 一 location 二 proxy pass 1 proxy pass包括ip和资源路径 结尾没有 2 proxy pass包括ip和资源路径 结尾有 3 proxy pass只包括ip 结尾有 4 prox
  • docker 中PyTorch训练时,Dataloader卡死、挂起,跑一个epoch停了,问题解决方案

    no space left on device shm 被占满了 直接设为8G
  • 二十三种设计模式第二十篇--备忘录模式

    备忘录模式 备忘录模式属于行为型模式 它允许在不破坏封装的情况下捕获和恢复对象的内部状态 保存一个对象的某个状态 以便在适当的时候恢复对象 该模式通过创建一个备忘录对象来保存原始对象的状态 并将其存储在一个负责管理备忘录的负责人对象中 备忘
  • 【转】awk、nawk、mawk、gawk的简答介绍

    转载 http blog sina com cn s blog 3d2d79aa0100h47h html awk 是一种编程语言 用于在linux unix下对文本和数据进行处理 数据可以来自标准输入 一个或多个文件 或其它命令的输出 即
  • Springboot 2 的@RequestParam接收数组异常解决!!!

    最近Vue 开发前端 然后向后台springboot 2 传递数组 发现springboot 2 接收数组方式无法使用 RequestParam ids List
  • Python中的三器一闭(详细版)

    python中的三器一闭 迭代器 什么是迭代 什么是可迭代对象 判断数据是否可迭代 什么是迭代器 迭代器的本质 使用迭代器取数据 自定义迭代器 生成器 创建生产器的方法 关键字yield next和send 装饰器 装饰器的功能 定义装饰器