Python生成器简介

生成器使您可以轻松地在Python中创建迭代,从而减少编写代码。 本教程将向您介绍Python生成器,它们的好处以及它们的工作方式。

基本

生成器是一个返回生成器对象的函数,您可以在该对象上调用next()方法,这样,每次调用它都会返回一个值或下一个值。 普通的Python函数使用return关键字返回值,但是生成器使用关键字yield返回值。 这意味着任何包含yield语句的Python函数都是生成器函数。

yield语句通常会暂停该函数并保存局部状态,以便可以从中断处继续恢复。 生成器函数可以具有一个或多个yield语句。

生成器也是迭代器,但是什么是迭代器? 在我们深入讨论生成器之前,我认为了解迭代器是很重要的,因为它们构成了本次讨论的组成部分。

Python迭代器

Python迭代器只是定义__iter__()方法的类。 大多数Python对象都是可迭代的,这意味着您可以遍历对象中的每个元素。 Python中可迭代的示例包括字符串,列表,元组,字典和范围。

让我们考虑下面的示例,其中我们遍历颜色列表:

colors= [“red”,”blue”,”yellow”]

def my_funct():
    for color in colors:
        print color

在幕后, for语句将在列表对象上调用iter() 。 然后,该函数将返回一个迭代器对象,该对象定义了__next__()方法,该方法随后将一次访问每种颜色。 当没有更多的颜色时, __next__ stopIteration将引发一个stopIteration异常,该异常将反过来通知for循环终止。

遍历字典

d = {'x': 10, 'y': 20, 'z': 30}
for k,v in d.items():
    print k, v

#result
# y 20
# x 10
# z 30

遍历CSV文件中的行

import csv

with open('file.csv', newline='') as File:  
    reader = csv.reader(File)
    for row in reader:
        yield row

遍历字符串

my_string = 'Generators'
for string in my_string:
    print (string)
    
#result

# G
# e
# n
# e
# r
# a
# t
# o
# r
# s

使用发电机的好处

让我们讨论使用生成器而不是迭代器的一些好处:

易于实施

在Python中构建迭代器将需要您使用__iter__()__next__()方法实现一个类,并注意可能导致stopIteration错误的任何错误。

class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]

如您在上面看到的,实现非常冗长。 所有这些负担由发电机自动处理。

更少的内存消耗

生成器有助于最大程度地减少内存消耗,尤其是在处理大型数据集时,因为生成器一次只会返回一项。

更好的性能和优化

发电机本质上是懒惰的。 这意味着它们仅在需要时才生成值。 与普通迭代器不同,在常规迭代器中,无论是否使用它们都会生成所有值,而生成器只会生成所需的值。 反过来,这将导致您的程序执行更快。

如何在Python中创建生成器

创建一个生成器非常容易。 您需要做的就是编写一个普通函数,但是使用yield语句而不是return语句,如下所示。

def gen_function():
    yield "python"

return语句完全终止一个函数时, yield只是暂停该函数,直到next()方法再次调用它为止。

例如,下面的程序同时使用yieldnext()语句。

def myGenerator(l):  
     total = 1
     for n in l:
       yield total
       total += n
     
newGenerator = myGenerator([10,3])

print(next(newGenerator))  
print(next(newGenerator))

Python生成器如何工作

让我们看看生成器是如何工作的。 考虑下面的示例。

# generator_example.py

def myGenerator(l):  
     total = 0
     for n in l:
       total += n
       yield total
      
     
newGenerator = myGenerator([10,20,30])

print(next(newGenerator))  
print(next(newGenerator))  
print(next(newGenerator))

在上面的函数中,我们定义了一个名为myGenerator的生成器,该生成器将列表l作为参数。 然后,我们定义一个变量total并将其赋值为零。 另外,我们遍历列表中的每个元素,然后将其添加到total变量中。

然后,我们实例化newGenerator并在其上调用next()方法。 这将运行代码,直到产生total的第一个值(在这种情况下为0 。 然后,该函数将保留total变量的值,直到下次调用该函数为止。 与普通的return语句(一次返回所有值)不同,生成器将从中断的地方开始提取。

以下是其余的后续值。

# generator_example.py

def myGenerator(l):  
     total = 0
     for n in l:
       yield total
       total += n
      
     
newGenerator = myGenerator([10,20,30])

print(next(newGenerator))  
print(next(newGenerator))  
print(next(newGenerator))  
  
# result

# 0
# 10
# 30

如果尝试在函数完成循环后调用该函数,则会收到StopIteration错误。

next()方法引发StopIteration ,以表明迭代器不再产生其他项。

0
10
30

Traceback (most recent call last):
  File "python", line 15, in <module>
StopIterationNormal function
例子2

在这个例子中,我们展示了如何在一个函数中使用多个yield语句。

# colors.py

def colors():
  yield "red"
  yield "blue"
  yield "green"
  
next_color =colors()
   
print(next(next_color))
print(next(next_color))
print(next(next_color))

# result

# red
# blue
# green

普通函数在调用该函数时会返回所有值,而生成器会等待直到再次调用next()方法。 调用next() ,颜色函数将从其停止处恢复。

结论

生成器的内存使用效率更高,尤其是在处理非常大的列表或大对象时。 这是因为您可以使用yield来处理较小的位,而不是一次将所有数据都存储在内存中。

此外,不要忘记查看我们可以在Envato Market上出售和进行研究的产品 ,也可以使用以下供稿随时提出任何问题并提供宝贵的反馈意见。

此外,如果您感到困惑,在课程部分中会有一门关于Python生成器的很好的课程。

翻译自: https://code.tutsplus.com/tutorials/introduction-to-python-generators--cms-29491

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值