栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

________在生成器和迭代器中__________和什么是方法包装器?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

________在生成器和迭代器中__________和什么是方法包装器?

特殊方法

__iter__
__next__
是创建迭代器类型的迭代器协议的一部分。为此,您必须区分两个独立的事物:
Iterablesiterators

Iterables 有些事情可以重复,通常情况下,这些都是某种包含物品的容器元素。常见的例子是列表,元组或字典。

为了迭代可迭代对象,您可以使用 iterator 。迭代器是帮助您遍历容器的对象。例如,当迭代列表时,迭代器本质上会跟踪您当前所处的索引。

为了获得一个迭代器,在迭代器

__iter__
上调用该方法。这就像一个工厂方法,将为此特定可迭代方法返回一个新的迭代器。具有
__iter__
定义的方法的类型将其转换为可迭代的。

迭代器通常需要单个方法,

__next__
该方法返回迭代的
一项。另外,为了使协议更易于使用,每个迭代器也应该是可迭代的,并在
__iter__
方法中返回自身。

作为一个简单的示例,这可能是列表的迭代器实现:

class ListIterator:    def __init__ (self, lst):        self.lst = lst        self.idx = 0    def __iter__ (self):        return self    def __next__ (self):        try: item = self.lst[self.idx]        except IndexError: raise StopIteration()        self.idx += 1        return item

然后,列表实现可以简单地

ListIterator(self)
__iter__
方法中返回。当然,列表的实际实现是在C中完成的,因此看起来有些不同。但是想法是一样的。

迭代器在Python中的各个地方都被不可见地使用。例如一个

for
循环:

for item in lst:    print(item)

这与以下内容相同:

lst_iterator = iter(lst) # this just calls `lst.__iter__()`while True:    try:        item = next(lst_iterator) # lst_iterator.__next__()    except StopIteration:        break    else:        print(item)

因此,for循环从可迭代对象请求一个迭代器,然后对其进行调用

__next__
,直到遇到
StopIteration
异常为止。这是在表面下发生的,这也是您还希望迭代器也实现的原因
__iter__
:否则,您将永远无法遍历迭代器。


对于生成器,人们通常所指的实际上是生成器 函数 ,即具有

yield
语句的某些函数定义。调用该生成器函数后,您将返回一个 generator
。生成器本质上只是一个迭代器,尽管它是花哨的(因为它比在容器中移动要多)。作为迭代器,它具有
__next__
“生成”下一个元素的
__iter__
方法和返回自身的方法。


生成器函数的示例如下:

def exampleGenerator():    yield 1    print('After 1')    yield 2    print('After 2')

包含

yield
语句的函数主体将其转换为生成器函数。这意味着在调用时,
exampleGenerator()
您将返回一个 生成器
对象。Generator对象实现了迭代器协议,因此我们可以对其进行调用
__next__
(或使用
next()
上面的函数):

>>> x = exampleGenerator()>>> next(x)1>>> next(x)After 12>>> next(x)After 2Traceback (most recent call last):  File "<pyshell#10>", line 1, in <module>    next(x)StopIteration

请注意,第一个

next()
呼叫尚未打印任何内容。这是关于生成器的特殊之处:它们是惰性的,并且仅评估必要的内容以从迭代器中获取下一项。只有第二次
next()
调用,我们才能从函数体中获得第一条打印行。而且我们需要另一个
next()
调用来耗尽可迭代对象(因为没有其他值可产生)。

但是除了这种懒惰之外,生成器的行为就像可迭代的一样。

StopIteration
最后,您甚至会遇到一个异常,该异常允许将生成器(和生成器函数)用作
for
循环源,并在任何可以使用“常规”可迭代项的地方使用。

发电机及其懒惰的最大好处是可以 按需
生产东西。一个很好的类比是在网站上无休止地滚动:您可以在之后(调用

next()
生成器)之后向下滚动项目,并且每隔一段时间,网站将不得不查询后端以检索更多项目以供您滚动浏览。理想情况下,这种情况不会引起您的注意。而这正是发电机的作用。它甚至允许这样的事情:

def counter():    x = 0    while True:        x += 1        yield x

非延迟的,由于这是一个无限循环,因此无法计算。但是懒惰地,作为生成器,有可能在一个项目之后消耗一个迭代的项目。我本来想让您不必将此生成器实现为完全自定义的迭代器类型,但是在这种情况下,这实际上并不是太困难,所以就来了:

class CounterGenerator:    def __init__ (self):        self.x = 0    def __iter__ (self):        return self    def __next__ (self):        self.x += 1        return self.x


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/645475.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号