简体   繁体   English

Python函数,它产生生成器和聚合结果

[英]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: 在我看来,我可以:

  1. Not make produce() a generator, but pass it a callback function to call on every item . 不要将produce()作为生成器,而是传递一个回调函数来调用每个item
  2. With every 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. 我宁愿不用每一次收益计算中间结果,只有在完成时。
  3. Send a dict as argument to produce() that will be populated with the aggregate results. dict作为参数发送到将用聚合结果填充的produce()
  4. Use a global to store aggregate results. 使用全局来存储聚合结果。

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.

相关问题 Python在生成器上聚合 - Python aggregate on a generator 生成和接收值的Python生成器 - Python generator that produces and receives values Python:递归 function 计算逆幂会产生奇怪的结果 - Python: Recursive function to calculate inverse power produces weird results Python代码不使用.COPY()函数会产生不正确的结果 - Python code produces incorrect results without using the .COPY() function 如何从python生成器向消费者函数发送额外的结果? - How to send extra results from a python generator to a consumer function? 如何使用 python 'in' 运算符和生成器 class 查询集结果在 function 中? - How to use python 'in' operator with generator class queryset results in function? 使用docstring记录Python函数,该docstring既可以原始形式读取,也可以产生良好的sphinx输出 - Documenting a Python function with a docstring that is both readable in raw form and produces good sphinx output Python 生成器和 set(generator) 得到不同的结果 - Python generator and set(generator) get different results PySNMP产生不正确的结果:NULL varBind值和Timeout同时 - PySNMP Produces Incorrect Results: Both NULL varBind Value and Timeout Simultaneously 汇总python中for循环的结果 - Aggregate results from for loop in python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM