这篇文章主要介绍了python如何自定义迭代器,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
对于新的和经验丰富的 Python 开发者来说,自定义迭代器是一个非常强大的但令人迷惑的主题。
许多内置类型,例如列表、集合和字典,已经实现了允许它们在底层迭代的协议。这使我们可以轻松地遍历它们。
>>> for food in ['Pizza', 'Fries']: print(food + '. Yum!') Pizza. Yum!Fries. Yum!
我们如何迭代我们自己的自定义类?首先,让我们来澄清一些术语。
要成为一个可迭代对象,一个类需要实现 __iter__()
__iter__()
方法需要返回一个迭代器
要成为一个迭代器,一个类需要实现 __next__()
(或在 Python 2中是 next()
),当没有更多的项要迭代时,必须抛出一个 StopIteration
异常。
呼!这听起来很复杂,但是一旦你记住了这些基本概念,你就可以在任何时候进行迭代。
我们什么时候想使用自定义迭代器?让我们想象一个场景,我们有一个 Server
实例在不同的端口上运行不同的服务,如 http
和 ssh
。其中一些服务处于 active
状态,而其他服务则处于 inactive
状态。
class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 80}, ]
当我们遍历 Server
实例时,我们只想遍历那些处于 active
的服务。让我们创建一个 IterableServer
类:
class IterableServer: def __init__(self): self.current_pos = 0 def __next__(self): pass # TODO: 实现并记得抛出 StopIteration
首先,我们将当前位置初始化为 0
。然后,我们定义一个 __next__()
方法来返回下一项。我们还将确保在没有更多项返回时抛出 StopIteration
。到目前为止都很好!现在,让我们实现这个 __next__()
方法。
class IterableServer: def __init__(self): self.current_pos = 0. # 我们初始化当前位置为 0 def __iter__(self): # 我们可以在这里返回 self,因为实现了 __next__ return self def __next__(self): while self.current_pos < len(self.services): service = self.services[self.current_pos] self.current_pos += 1 if service['active']: return service['protocol'], service['port'] raise StopIteration next = __next__ # 可选的 Python2 兼容性
我们对列表中的服务进行遍历,而当前的位置小于服务的个数,但只有在服务处于活动状态时才返回。一旦我们遍历完服务,就会抛出一个 StopIteration
异常。
因为我们实现了 __next__()
方法,当它耗尽时,它会抛出 StopIteration
。我们可以从 __iter__()
返回 self
,因为 IterableServer
类遵循 iterable
协议。
现在我们可以遍历一个 IterableServer
实例,这将允许我们查看每个处于活动的服务,如下所示:
>>> for protocol, port in IterableServer(): print('service %s is running on port %d' % (protocol, port)) service ssh is running on port 22 service http is running on port 21
太棒了,但我们可以做得更好!在这样类似的实例中,我们的迭代器不需要维护大量的状态,我们可以简化代码并使用 generator(生成器) 来代替。
class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 21}, ] def __iter__(self): for service in self.services: if service['active']: yield service['protocol'], service['port']
yield
关键字到底是什么?在定义生成器函数时使用 yield。这有点像 return
,虽然 return
在返回值后退出函数,但 yield
会暂停执行直到下次调用它。这允许你的生成器的功能在它恢复之前保持状态。查看 yield 的文档以了解更多信息。使用生成器,我们不必通过记住我们的位置来手动维护状态。生成器只知道两件事:它现在需要做什么以及计算下一个项目需要做什么。一旦我们到达执行点,即 yield
不再被调用,我们就知道停止迭代。
这是因为一些内置的 Python 魔法。在 Python 关于 __iter__()
的文档中我们可以看到,如果 __iter__()
是作为一个生成器实现的,它将自动返回一个迭代器对象,该对象提供 __iter__()
和 __next__()
方法。阅读这篇很棒的文章,深入了解迭代器,可迭代对象和生成器。
感谢你能够认真阅读完这篇文章,希望小编分享的“python如何自定义迭代器”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。