百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一文掌握Python 生成器_python生成app

itomcoil 2025-02-17 12:30 21 浏览

ython 生成器有助于实现维护持久状态的功能。这支持增量计算和迭代。此外,可以使用生成器代替数组以节省内存。这是因为生成器不存储值,而是存储具有函数状态的计算逻辑,类似于准备触发的未计算函数实例。

生成器表达式

可以使用生成器表达式代替数组创建操作。与数组不同,生成器将在运行时生成数字。

>>> import sys
>>> a = [x for x in range(1000000)]
>>> b = (x for x in range(1000000))
>>> sys.getsizeof(a)
8697472
>>> sys.getsizeof(b)
128
>>> a
[0, 1, ... 999999]
>>> b
 at 0x1020de6d0>

我们可以看到,在上面的场景中,我们通过使用生成器代替数组节省了相当多的内存。

用 yield 代替 return 的函数

让我们考虑一个简单的例子,你想生成任意数量的素数。以下是检查一个数字是否为素数的函数以及将为我们产生无限多个素数的生成器。

def isPrime(n):
    if n < 2 or n % 1 > 0:
        return False
    elif n == 2 or n == 3:
        return True
    for x in range(2, int(n**0.5) + 1):
        if n % x == 0:
            return False
    return Truedef getPrimes():
    value = 0
    while True:
        if isPrime(value):
            yield value
        value += 1

正如你在第二个函数中看到的,我们在 while 循环中迭代并产生质数。让我们看看如何使用上面的生成器。

primes = getPrimes()>>> next(primes)
2
>>> next(primes)
3
>>> next(primes)
5

首先,我们调用函数并获取生成器实例。虽然这可以模拟无限数组,但目前还没有找到任何元素。如果调用 list(primes),程序可能会因 MemoryError 而崩溃。但是,对于素数,它不会去那里,因为素数空间是稀疏的,计算可以在有限的时间内达到内存限制。但是,对于发电机,您不会事先知道长度。如果你调用 len(primes),你将得到以下错误,原因与数字仅在运行时生成的原因相同。

----------------------------------------------------------------
TypeError                      Traceback (most recent call last)
 in 
----> 1 len(primes)

TypeError: object of type 'generator' has no len()

迭代次数有限的生成器

尽管我们的素数示例具有无限的迭代空间,但在大多数日常场景中,我们面临的是有限计算。因此,让我们看一个示例,我们可以使用它来读取包含文本数据的文件以及下一行句子的语义分数。

为什么我们需要使用 yield?

假设文件为 1TB,单词语料库为 500000。它不适合内存。一个简单的解决方案是一次读取 2 行,计算每行的单词字典,并在下一行返回语义分数。该文件将如下所示。

The product is well packed
5
Edges of the packaging was damaged and print was faded.
3
Avoid this product. Never going to buy anything from ShopX.
1
Shipping took a very long time
2

很明显,我们不需要立即打开文件。此外,这些行必须矢量化,并可能保存到另一个文件中,该文件可以直接解析以训练机器学习模型。因此,为我们提供干净代码的选项是使用一个生成器,该生成器将一次读取两行,并将数据和语义分数作为元组提供给我们。

实现文件解析生成器

假设我们在名为 test.txt 的文件中有上述文本文档。我们将使用以下生成器函数来读取文件。

def readData(path):
    with open(path) as f:
        sentiment = ""
        line = ""
        for n, d in enumerate(f):
            if n % 2 == 0:
                line = d.strip()
            else:
                sentiment = int(d.strip())
                yield line, sentiment

我们可以在 for 循环中使用上述函数,如下所示。

>>> data = readData("test.txt")
>>> for l, s in data: print(l, s)
The product is well packed 5
Edges of the packaging was damaged and print was faded. 3
Avoid this product. Never going to buy anything from ShopX. 1
Shipping took a very long time 2

生成器如何退出?

在正常的 for 循环中,当生成器不再执行 yielding 时,迭代将停止。但是,我们可以通过在生成器实例上手动调用 next() 来观察到这一点。在迭代限制之外调用 next() 将引发以下异常。

----------------------------------------------------------------
StopIteration                  Traceback (most recent call last)
 in 
---> 28 print(next(data))StopIteration:

使用 send、throw 和 close

send 函数

让我们回顾一下我们的素数示例。想象一下,我们想将生成器函数的值重置为 100,如果它们是质数,则开始产生大于 100 的值。我们可以在生成器实例上使用 send() 方法将值推送到生成器中,如下所示。

>>> primes = getPrimes()
>>> next(primes)
2
>>> primes.send(10)
11
>>> primes.send(100)
101

请注意,在调用 send() 之前,我们必须至少调用 next() 一次。让我们看看如何修改我们的函数以适应目的。因为函数应该知道如何分配接收到的值。

def getPrimes():
    value = 0
    while True:
        if isPrime(value):
            i = yield value
            if i is not None:
                value = i
        value += 1

我们将 yield 值存储在变量 i 中。如果不是 None 类型,我们将其分配给 value 变量。None 检查是必不可少的,因为第一个 next()value 变量中没有 value to yield。

throw 函数

假设您希望以大于 10 的值结束迭代,以避免溢出或超时(假设)。throw() 函数可用于提示生成器停止引发异常。

primes = getPrimes()for x in primes:
    if x > 10:
        primes.throw(ValueError, "Too large")
    print(x)

此技术可用于验证输入。逻辑在于生成器的用户。这将产生以下输出。

2
3
5
7----------------------------------------------------------------
ValueError                     Traceback (most recent call last)
 in 
     12 for x in primes:
     13     if x > 10:
---> 14         primes.throw(ValueError, "Too large")
     15     print(x)

 in getPrimes()
      3     while True:
      4         if isPrime(value):
----> 5             i = yield value
      6             if i is not None:
      7                 value = i

ValueError: Too large

close 函数

手头无一例外地处理瓶盖通常是优雅的。在这种情况下,close() 函数可用于有效地关闭迭代器。

primes = getPrimes()for x in primes:
    if x > 10:
        primes.close()
    print(x)

这将得到以下输出。

2
3
5
7
11

请注意,我们的值为 11,这是最后一个计算出的大于 11 的值。这模拟了 C/C++ 中 do while 循环的行为。

相关推荐

Python Qt GUI设计:将UI文件转换Python文件三种妙招(基础篇—2)

在开始本文之前提醒各位朋友,Python记得安装PyQt5库文件,Python语言功能很强,但是Python自带的GUI开发库Tkinter功能很弱,难以开发出专业的GUI。好在Python语言的开放...

Connect 2.0来了,还有Nuke和Maya新集成

ftrackConnect2.0现在可以下载了--重新设计的桌面应用程序,使用户能够将ftrackStudio与创意应用程序集成,发布资产等。这个新版本的发布中还有两个Nuke和Maya新集成,...

Magicgui:不会GUI编程也能轻松构建Python GUI应用

什么是MagicguiMagicgui是一个Python库,它允许开发者仅凭简单的类型注解就能快速构建图形用户界面(GUI)应用程序。这个库基于Napari项目,利用了Python的强大类型系统,使得...

Python入坑系列:桌面GUI开发之Pyside6

阅读本章之后,你可以掌握这些内容:Pyside6的SignalsandSlots、Envents的作用,如何使用?PySide6的Window、DialogsandAlerts、Widgets...

Python入坑系列-一起认识Pyside6 designer可拖拽桌面GUI

通过本文章,你可以了解一下内容:如何安装和使用Pyside6designerdesigner有哪些的特性通过designer如何转成python代码以前以为Pyside6designer需要在下载...

pyside2的基础界面(pyside2显示图片)

今天我们来学习pyside2的基础界面没有安装过pyside2的小伙伴可以看主页代码效果...

Python GUI开发:打包PySide2应用(python 打包pyc)

之前的文章我们介绍了怎么使用PySide2来开发一个简单PythonGUI应用。这次我们来将上次完成的代码打包。我们使用pyinstaller。注意,pyinstaller默认会将所有安装的pack...

使用PySide2做窗体,到底是怎么个事?看这个能不能搞懂

PySide2是Qt框架的Python绑定,允许你使用Python创建功能强大的跨平台GUI应用程序。PySide2的基本使用方法:安装PySide2pipinstallPy...

pycharm中conda解释器无法配置(pycharm安装的解释器不能用)

之前用的好好的pycharm正常配置解释器突然不能用了?可以显示有这个环境然后确认后可以conda正在配置解释器,但是进度条结束后还是不成功!!试过了pycharm重启,pycharm重装,anaco...

Conda使用指南:从基础操作到Llama-Factory大模型微调环境搭建

Conda虚拟环境在Linux下的全面使用指南:从基础操作到Llama-Factory大模型微调环境搭建在当今的AI开发与数据分析领域,conda虚拟环境已成为Linux系统下管理项目依赖的标配工具。...

Python操作系统资源管理与监控(python调用资源管理器)

在现代计算环境中,对操作系统资源的有效管理和监控是确保应用程序性能和系统稳定性的关键。Python凭借其丰富的标准库和第三方扩展,提供了强大的工具来实现这一目标。本文将探讨Python在操作系统资源管...

本地部署开源版Manus+DeepSeek创建自己的AI智能体

1、下载安装Anaconda,设置conda环境变量,并使用conda创建python3.12虚拟环境。2、从OpenManus仓库下载代码,并安装需要的依赖。3、使用Ollama加载本地DeepSe...

一文教会你,搭建AI模型训练与微调环境,包学会的!

一、硬件要求显卡配置:需要Nvidia显卡,至少配备8G显存,且专用显存与共享显存之和需大于20G。二、环境搭建步骤1.设置文件存储路径非系统盘存储:建议将非安装版的环境文件均存放在非系统盘(如E盘...

使用scikit-learn为PyTorch 模型进行超参数网格搜索

scikit-learn是Python中最好的机器学习库,而PyTorch又为我们构建模型提供了方便的操作,能否将它们的优点整合起来呢?在本文中,我们将介绍如何使用scikit-learn中的网格搜...

如何Keras自动编码器给极端罕见事件分类

全文共7940字,预计学习时长30分钟或更长本文将以一家造纸厂的生产为例,介绍如何使用自动编码器构建罕见事件分类器。现实生活中罕见事件的数据集:背景1.什么是极端罕见事件?在罕见事件问题中,数据集是...