在__iter __()中使用yield有什么好处? [英] What's the advantage of using yield in __iter__()?

查看:438
本文介绍了在__iter __()中使用yield有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

__iter__()函数中使用generator(yield)有什么好处?阅读完 Python Cookbook 之后,我了解到如果您希望生成器向用户公开额外的状态,请不要忘记,您可以轻松地 将其实现为一个类,将生成器功能代码放在__iter__()方法中."

What is the advantage of using an generator(yield) inside an __iter__() function? After reading through Python Cookbook I understand "If you want a generator to expose extra state to the user, don’t forget that you can easily implement it as a class, putting the generator function code in the __iter__() method."

import io

class playyield:
    def __init__(self,fp):
        self.completefp = fp

    def __iter__(self):
        for line in self.completefp:
            if 'python' in line:
                yield line

if __name__ =='__main__':
    with io.open(r'K:\Data\somefile.txt','r') as fp:
        playyieldobj = playyield(fp)
        for i in playyieldobj:
            print I

问题:

  1. 额外状态在这里意味着什么?
  2. __iter__ ()中使用yield而不是对yield使用单独的功能有什么好处?
  1. What does extra state means here?
  2. What is the advantage of using yield inside __iter__ () instead of using a separate function for yield?

推荐答案

如果不遵循生成器功能,则要遵循最佳做法,则必须实现类似这样的功能:

Without generator functions, you would have to implement something like this, if you want to follow best practices:

In [7]: class IterableContainer:
   ...:     def __init__(self, data=(1,2,3,4,5)):
   ...:         self.data = data
   ...:     def __iter__(self):
   ...:         return IterableContainerIterator(self.data)
   ...:

In [8]: class IterableContainerIterator:
   ...:     def __init__(self, data):
   ...:         self.data = data
   ...:         self._pos = 0
   ...:     def __iter__(self):
   ...:         return self
   ...:     def __next__(self):
   ...:         try:
   ...:              item = self.data[self._pos]
   ...:         except IndexError:
   ...:             raise StopIteration
   ...:         self._pos += 1
   ...:         return item
   ...:

In [9]: container = IterableContainer()

In [10]: for x in container:
    ...:     print(x)
    ...:
1
2
3
4
5

当然,上面的示例是人为设计的,但希望您能理解.使用生成器,可以简单地是:

Of course, the above example is contrived, but hopefully you get the point. With generators, this can simply be:

In [11]: class IterableContainer:
    ...:     def __init__(self, data=(1,2,3,4,5)):
    ...:         self.data = data
    ...:     def __iter__(self):
    ...:         for x in self.data:
    ...:             yield x
    ...:
    ...:

In [12]: list(IterableContainer())
Out[12]: [1, 2, 3, 4, 5]

关于状态,正好是-对象可以具有状态,例如属性.您可以在运行时操纵该状态.您可以进行以下操作,但是我不建议这样做:

As for state, well, it's exactly that - objects can have state, e.g. attributes. You can manipulate that state at runtime. You could do something like the following, although, I would say it is highly inadvisable:

In [19]: class IterableContainerIterator:
    ...:     def __init__(self, data):
    ...:         self.data = data
    ...:         self._pos = 0
    ...:     def __iter__(self):
    ...:         return self
    ...:     def __next__(self):
    ...:         try:
    ...:              item = self.data[self._pos]
    ...:         except IndexError:
    ...:             raise StopIteration
    ...:         self._pos += 1
    ...:         return item
    ...:     def rewind(self):
    ...:         self._pos = min(0, self._pos - 1)
    ...:

In [20]: class IterableContainer:
    ...:     def __init__(self, data=(1,2,3,4,5)):
    ...:         self.data = data
    ...:     def __iter__(self):
    ...:         return IterableContainerIterator(self.data)
    ...:

In [21]: container = IterableContainer()

In [22]: it = iter(container)

In [23]: next(it)
Out[23]: 1

In [24]: next(it)
Out[24]: 2

In [25]: it.rewind()

In [26]: next(it)
Out[26]: 1

In [27]: next(it)
Out[27]: 2

In [28]: next(it)
Out[28]: 3

In [29]: next(it)
Out[29]: 4

In [30]: next(it)
Out[30]: 5

In [31]: it.rewind()

In [32]: next(it)
Out[32]: 1

这篇关于在__iter __()中使用yield有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆