[英]Python function that produces both generator and aggregate results
What is the Pythonic way to make a generator that also produces aggregate results? 什么是Pythonic方法来生成也能产生聚合结果的生成器? In meta code, something like this (but not for real, as my Python version does not support mixing yield and return): 在元代码中,类似这样的东西(但不是真实的,因为我的Python版本不支持混合yield和return):
def produce():
total = 0
for item in find_all():
total += 1
yield item
return total
As I see it, I could: 在我看来,我可以:
produce()
a generator, but pass it a callback function to call on every item
. 不要将produce()
作为生成器,而是传递一个回调函数来调用每个item
。 yield
, also yield
the aggregate results up until now. 随着每一个yield
,直到现在还yield
汇总结果。 I'd rather not calculate the intermediate results with every yield, only when finishing. 我宁愿不用每一次收益计算中间结果,只有在完成时。 dict
as argument to produce()
that will be populated with the aggregate results. 将dict
作为参数发送到将用聚合结果填充的produce()
。 All of them don't seem very attractive... 所有这些看起来都不太吸引人......
NB. NB。 total
is a simple example, my actual code requires complex aggregations. total
是一个简单的例子,我的实际代码需要复杂的聚合。 And I need intermediate results before produce()
finishes, hence a generator. 而且我需要在produce()
完成之前produce()
中间结果,因此需要一个生成器。
Maybe you shouldn't use a generator but an iterator. 也许你不应该使用生成器而是使用迭代器。
def findall(): # no idea what your "find_all" does so I use this instead. :-)
yield 1
yield 2
yield 3
class Produce(object):
def __init__(self, iterable):
self._it = iterable
self.total = 0
def __iter__(self):
return self
def __next__(self):
self.total += 1
return next(self._it)
next = __next__ # only necessary for python2 compatibility
Maybe better to see this with an example: 也许更好地看一个例子:
>>> it = Produce(findall())
>>> it.total
0
>>> next(it)
1
>>> next(it)
2
>>> it.total
2
you can use enumerate to count stuff, for example 例如,您可以使用枚举来计算内容
i=0
for i,v in enumerate(range(10), 1 ):
print(v)
print("total",i)
(notice the start value of the enumerate) (注意枚举的起始值)
for more complex stuff, you can use the same principle, make produce a generator that yield both values and ignore one in the iteration and use it later when finished. 对于更复杂的东西,你可以使用相同的原理,make产生一个产生两个值的生成器,并在迭代中忽略一个,并在完成后使用它。
other alternative is passing a modifiable object, for example 例如,另一种选择是传递可修改的对象
def produce(mem):
t=0
for x in range(10):
t+=1
yield x
mem.append(t)
aggregate=[]
for x in produce(aggregate):
print(x)
print("total",aggregate[0])
in either case the result is the same for this example 在任何一种情况下,该示例的结果都是相同的
0
1
2
3
4
5
6
7
8
9
total 10
Am I missing something? 我错过了什么吗? Why not: 为什么不:
def produce():
total = 0
for item in find_all():
total += 1
yield item
yield total
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.