- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从生成器收到了未知数量的后台处理记录。如果有更重要的工作,我就得停下来释放进程。
main
流程最好描述为:
def main():
generator_source = generator_for_test_data() # 1. contact server to get data.
uw = UploadWrapper(generator_source) # 2. wrap the data.
while not interrupt(): # 3. check for interrupts.
row = next(uw)
if row is None:
return
print(long_running_job(row)) # 4. do the work.
有没有一种方法可以在不插入__iter__
的情况下到达__next__
?有两个步骤 - (1) 创建一个迭代器,然后 (2) 迭代它,看起来很笨拙。
在很多情况下,我更愿意将函数提交给函数管理器(mapreduce 样式),但在这种情况下,我需要一个带有一些设置的实例化类。因此,注册单个函数仅当该函数单独为 __next__
class UploadWrapper(object):
def __init__(self, generator):
self.generator = generator
self._iterator = None
def __iter__(self):
for page in self.generator:
yield from page.data
def __next__(self):
if self._iterator is None: # ugly bit.
self._iterator = self.__iter__() #
try:
return next(self._iterator)
except StopIteration:
return None
问:有没有更简单的方法?
<小时/>为了完整性而添加的工作示例:
import time
import random
class Page(object):
def __init__(self, data):
self.data = data
def generator_for_test_data():
for t in range(10):
page = Page(data=[(t, i) for i in range(100, 110)])
yield page
def long_running_job(row):
time.sleep(random.randint(1,10)/100)
assert len(row) == 2
assert row[0] in range(10)
assert row[1] in range(100, 110)
return row
def interrupt(): # interrupt check
if random.randint(1,50) == 1:
print("INTERRUPT SIGNAL!")
return True
return False
class UploadWrapper(object):
def __init__(self, generator):
self.generator = generator
self._iterator = None
def __iter__(self):
for ft in self.generator:
yield from ft.data
def __next__(self):
if self._iterator is None:
self._iterator = self.__iter__()
try:
return next(self._iterator)
except StopIteration:
return None
def main():
gen = generator_for_test_data()
uw = UploadWrapper(gen)
while not interrupt(): # check for job interrupt.
row = next(uw)
if row is None:
return
print(long_running_job(row))
if __name__ == "__main__":
main()
最佳答案
您的UploadWrapper
看起来过于复杂,但其实不止一个更简单的解决方案。
我的第一个想法是完全放弃这个类,只使用一个函数:
def uploadwrapper(page_gen):
for page in page_gen:
yield from page.data
只需替换 uw = UploadWrapper(gen)
与 uw = uploadwrapper(gen)
,这样就可以了。
如果你坚持上课,你可以去掉 __next__()
并替换uw = UploadWrapper(gen)
与 uw = iter(UploadWrapper(gen))
,它会起作用的。
无论哪种情况,您还必须捕获 StopIteration
在调用者中。 __next__()
应该筹集 StopIteration
完成后,不返回 None
,就像你的一样。否则,它无法处理需要行为良好的迭代器的事物,例如。 for
循环。
我认为您可能对这一切应该如何组合在一起有一些误解,所以我将尽力解释它应该如何工作,据我所知:
__iter__()
的要点是如果你有例如。一个列表,可以通过调用 iter()
得到多个独立的迭代器。当你有 for
循环,你基本上首先得到一个带有 iter()
的迭代器然后调用next()
在每个循环迭代中。如果您有两个使用相同列表的嵌套循环,则迭代器及其位置仍然是分开的,因此不会发生冲突。 __iter__()
应该返回它所在容器的迭代器,或者如果在迭代器上调用它,它应该只返回 self
。从这个意义上说,UploadWrapper
有点错误。不回self
在__iter__()
,因为它包装了一个生成器,所以不能真正给出独立的迭代器。至于为什么漏掉__next__()
有效,这是因为当您定义生成器时(即在函数中使用 yield
),生成器有一个 __iter__()
(返回 self
,因为它应该)和 __next__()
这正如你所期望的那样。在您的原始代码中,您并没有真正使用 __iter__()
完全符合它的用途:即使您将其重命名为其他名称,该代码也可以工作!这是因为你从来没有打电话过iter()
在实例上,直接调用next()
即可.
如果你想在类里面“正确”地做到这一点,我认为这样的事情可能就足够了:
class UploadWrapper(object):
def __init__(self, generator):
self.generator = generator
self.subgen = iter(next(generator).data)
def __iter__(self):
return self
def __next__(self):
while True:
try:
return next(self.subgen)
except StopIteration:
self.subgen = iter(next(self.generator).data)
关于python - 将生成器包装为单个 `next` 调用,而不是两个步骤( __iter__ + __next__ ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51657482/
我有一个看起来像这样的类 Class myClass: def __init__(self, key, value): self.key = key self.
我正在编写一个返回自身修改的迭代器对象,我希望原始对象成为迭代过程的一部分,因此需要在修改之前返回它。 ...但是: 创建要返回的对象的深拷贝非常耗时。 对象有很多属性,所以定义辅助变量似乎不是一个优
我看到 next = __next__ 出现在 OOP 代码的多个地方。 这样做的目的是什么?即使没有这条线,它也适用于我。 class Iter: def __init__(self, va
我正在尝试模拟协程。因此,此模拟的 __next__() 和 close() 被调用。虽然模拟 close() 有效,但我无法模拟 __next__(): mock_coroutine = m
我正在阅读有关生成器和迭代器以及 __next__() 的作用的文章. '__next__' in dir(mygen) .是真的 '__next__' in dir(mylist) ,是假的 当我深
我正在编写双向链表的实现。为了遍历列表,我使用了类似的东西: class Node: """ A node in our linked list """ def __init__(se
我使用的是 Python 2.7。 按照惯例,__iter__、__init__、__str__ 等内置方法使用双下划线来标识它们。为什么 next() 函数没有这个? 它与这里的其他内置函数一起
我正在尝试为迭代器创建自己的类,并找到了这样一个示例: class OddNum: """Class to implement iterator protocol""" def __init_
UPDATE(反映最先进的知识水平)状态:2017-05-12 进行此更新的原因是,当我问这个问题时,我并不知道我发现了有关Python3如何“在幕后”工作的信息。 从所有得出的结论是: 如果您为迭代
我现在正在研究一个双向链表类,我的 next 和 iter 方法遇到了麻烦。这是我类(class)的一个项目,我已经提交了该项目,现在只想了解如何实际修复它以使其有用。 我希望我的代码做的是设置一个当
在 Python 3 中,通过定义 __iter__ 和 __next__ 方法使类同时成为可迭代对象和迭代器是标准过程。但是我很难解决这个问题。以这个创建一个只产生偶数的迭代器的例子为例: clas
我正在研究制作可迭代对象,我想知道这两个选项中的哪一个更像 pythonic/更好的方法,是没有区别还是我对使用 yield 的想法有误?对我来说,使用 yield 似乎更干净,而且显然它比使用 __
我正在使用 yield 在我的类中的 __next__() 函数中返回下一个值。但是它不返回下一个值,它返回生成器对象。 我正在尝试更好地理解迭代器和 yield。我可能做错了。 看看。 class
我从生成器收到了未知数量的后台处理记录。如果有更重要的工作,我就得停下来释放进程。 main 流程最好描述为: def main(): generator_source = generator
如果我们有以下代码: s = "stackoverflow" si = iter(s) si.__next__() # Would return s si.__next__() # Would ret
我对 python 迭代器有点迷茫。我偶尔会使用它们,但我不记得自己创建过一个。我从某个地方读到的,我不记得在哪里,像这样的代码: class Foo(object): def __init_
我想使用跳过某些元素的 __next__ 创建一个 Python 迭代器类。 例如,我在这里使用 yield 和 continue 实现了一个生成器,我希望它下面的迭代器类做完全相同的事情。 def
>>> s = 'spam' >>> s.__next__() 结果是:回溯(最近调用最后): 文件“”,第 1 行,位于 s._下一个_()AttributeError:“str”对象没有属性“_n
来自 Learning python 书第 5 版: Page 421, footnote2: Technically speaking, the for loop calls the interna
我是一名优秀的程序员,十分优秀!