Python 共享迭代器的单个迭代

Python 共享迭代器的单个迭代,python,iterator,Python,Iterator,我有很多数据,通常在一个文件中。我想计算一些量,所以我有这样的函数: def mean(iterator): n = 0 sum = 0. for i in iterator: sum += i n += 1 return sum / float(n) 我还有许多其他类似的函数(var,size,…) 现在我有一个迭代器在数据中迭代:iter\u data。我可以计算所有我想要的量:m=mean(iter\u数据);v=var(iter_

我有很多数据,通常在一个文件中。我想计算一些量,所以我有这样的函数:

def mean(iterator):
    n = 0
    sum = 0.
    for i in iterator:
      sum += i
      n += 1
    return sum / float(n)
我还有许多其他类似的函数(
var
size
,…)

现在我有一个迭代器在数据中迭代:
iter\u data
。我可以计算所有我想要的量:
m=mean(iter\u数据);v=var(iter_data)
等等,但问题是我迭代了很多次,在我的例子中这是非常昂贵的。实际上,I/O是最昂贵的部分

所以问题是:我能不能计算我的量
m,v,…
iter\u数据上只迭代一次
保持函数
mean
var
。。。这样就很容易添加新的

我需要的是类似的东西,您可以使用和生成器magic(我说magic是因为它不太好读):

顺便说一下,您可以用一种更简单的方式编写
mean

def mean(iterator):
    total = 0.
    for n, item in enumerate(iterator, 1):
         total += i
         yield
    yield total / n

您不应该为变量命名
sum
,因为这会隐藏具有相同名称的内置函数。

您想要的是有一个主
Calc
类,该类对数据进行迭代,对
mean
var
等应用不同的计算,然后可以通过接口返回这些值。您可以让计算在主计算之前向此类注册,然后通过接口中的新访问器获得结果,从而使其更通用。

例如,使用对象和回调,如:

class Counter():
    def __init__(self):
        self.n = 0
    def __call__(self, i):
        self.n += 1

class Summer():
    def __init__(self):
        self.sum = 0
    def __call__(self, i):
        self.sum += i


def process(iterator, callbacks):
    for i in iterator:
        for f in callbacks: f(i)

counter = Counter()
summer = Summer()
callbacks = [counter, summer]
iterator = xrange(10) # testdata
process(iterator, callbacks)

# process results from callbacks
n = counter.n
sum = summer.sum

这很容易扩展,并且只对数据进行一次迭代。

如果没有类,您可以调整以下内容:

def my_mean():
    total = 0.
    length = 0
    while True:
        val = (yield)
        if val is not None:
            total += val
            length += 1
        else:
            yield total / length

def my_len():
    length = 0
    while True:
        val = (yield)
        if val is not None:
            length += 1
        else:
            yield length

def my_sum():
    total = 0.
    while True:
        val = (yield)
        if val is not None:
            total += val
        else:
            yield total


def process(iterable, **funcs):
    fns = {name:func() for name, func in funcs.iteritems()}
    for fn in fns.itervalues():
        fn.send(None)
    for item in iterable:
        for fn in fns.itervalues():
            fn.send(item)
    return {name:next(func) for name, func in fns.iteritems()}


data = [1, 2, 3]
print process(data, items=my_len, some_other_value=my_mean, Total=my_sum)
# {'items': 3, 'some_other_value': 2.0, 'Total': 6.0}

您可以使用一个循环将所有函数绑定到一个函数中,并返回一个包含所有计算值的字典,如
{'mean':2.7,'var':0.2,'size':27}
,等等@MrE:no,在您的解决方案中,您并没有将函数分开,而是以相同的方式计算均值和方差function@Brionius,同样的问题。正如我在问题中所说:将函数分开是不是数据太大,无法放入内存?否则迭代可能会很快,您可以使用例如numpy。
def my_mean():
    total = 0.
    length = 0
    while True:
        val = (yield)
        if val is not None:
            total += val
            length += 1
        else:
            yield total / length

def my_len():
    length = 0
    while True:
        val = (yield)
        if val is not None:
            length += 1
        else:
            yield length

def my_sum():
    total = 0.
    while True:
        val = (yield)
        if val is not None:
            total += val
        else:
            yield total


def process(iterable, **funcs):
    fns = {name:func() for name, func in funcs.iteritems()}
    for fn in fns.itervalues():
        fn.send(None)
    for item in iterable:
        for fn in fns.itervalues():
            fn.send(item)
    return {name:next(func) for name, func in fns.iteritems()}


data = [1, 2, 3]
print process(data, items=my_len, some_other_value=my_mean, Total=my_sum)
# {'items': 3, 'some_other_value': 2.0, 'Total': 6.0}