Python 确定生成器生成的值的数量

Python 确定生成器生成的值的数量,python,python-3.x,Python,Python 3.x,假设我有以下代码: counter = Counter() text = f.read() words = words_generator(text) interesting_words = filter_generator(words) counter.update(interesting_words) for i in counter: print("Frequency for "+i ": "+counter[i]/sum) 我应该如何最好地设置sum的值,sum是由words

假设我有以下代码:

counter = Counter()
text = f.read()
words = words_generator(text)
interesting_words = filter_generator(words)
counter.update(interesting_words)

for i in counter:
    print("Frequency for "+i ": "+counter[i]/sum)
我应该如何最好地设置sum的值,sum是由words\u生成器生成的值的数量

基本上,CountItemsWrapper是一个迭代器,它只传递值,但无论何时都保持计数

然后,您可以只使用包装器上的count属性作为总和

课堂讲解:

def __init__(self, items):
    self.items = iter(items)
    self.count = 0
这很简单。请记住,实例是迭代器,而不仅仅是iterables。所以这个循环一次,保持计数一次

调用此函数是为了获取下一项。self.count必须在调用下一项之后添加,因为我们允许StopIteration传播,如果我们没有生成值,则不希望添加到计数

这是一个迭代器,因此它返回自身

基本上,CountItemsWrapper是一个迭代器,它只传递值,但无论何时都保持计数

然后,您可以只使用包装器上的count属性作为总和

课堂讲解:

def __init__(self, items):
    self.items = iter(items)
    self.count = 0
这很简单。请记住,实例是迭代器,而不仅仅是iterables。所以这个循环一次,保持计数一次

调用此函数是为了获取下一项。self.count必须在调用下一项之后添加,因为我们允许StopIteration传播,如果我们没有生成值,则不希望添加到计数


这是一个迭代器,因此它会自动返回。

Q&D可行的技术解决方案:将生成器包装到一个iterable中,以跟踪看到的项目数,即:

class IterCount(object):
    def __init__(self, iterable):
        self._iterable = iterable
        self._count = 0

    def _itercount(self):
        for value in self._iterable:
            self._count += 1
            yield value

    def __iter__(self):
        return self._itercount()

    @property
    def count(self):
        return self._count


itc1 = IterCount(range(10))
print list(itc1)
print itc1.count

itc2 = IterCount(xrange(10))
print list(itc2)
print itc2.count

Q&D可行的技术解决方案:将您的生成器包装成一个iterable,用于跟踪所看到的项目数量,即:

class IterCount(object):
    def __init__(self, iterable):
        self._iterable = iterable
        self._count = 0

    def _itercount(self):
        for value in self._iterable:
            self._count += 1
            yield value

    def __iter__(self):
        return self._itercount()

    @property
    def count(self):
        return self._count


itc1 = IterCount(range(10))
print list(itc1)
print itc1.count

itc2 = IterCount(xrange(10))
print list(itc2)
print itc2.count

最简单的解决方案是建立一个列表:

words = list(words_generator(text))
另一个选项是使用itertools.tee:

之后,您可以使用iterable的两个副本。但是请注意,如果您首先完全迭代一个副本,那么简单地构建列表将更快、内存效率更高。要查看内存方面的任何增益,您应该以某种方式同时对两个副本进行迭代。 例如:

filtered = filter_generator(words)
total = 0
for word, _ in zip(filtered, words_copy): # use itertools.izip in python2
    counter[word] += 1
    total += 1
total += sum(1 for _ in words_copy)
它最多使用On-k内存,其中n是文本中的单词数,k是文本中感兴趣的单词数。您可以使用以下方法稍微简化代码:

from itertools import zip_longest #izip_longest in python2
filtered = filter_generator(words)
total = 0
for word, _ in zip_longest(filtered, words_copy):
    counter[word] += 1
    total += 1
del counter[None]
如果生成器是恒定空间,则只使用O1内存


但是请注意,使用显式循环会降低代码的速度,因此最终,如果内存不是一个选项,那么构建单词列表可能是更好的解决方案。

最简单的解决方案是构建一个列表:

words = list(words_generator(text))
另一个选项是使用itertools.tee:

之后,您可以使用iterable的两个副本。但是请注意,如果您首先完全迭代一个副本,那么简单地构建列表将更快、内存效率更高。要查看内存方面的任何增益,您应该以某种方式同时对两个副本进行迭代。 例如:

filtered = filter_generator(words)
total = 0
for word, _ in zip(filtered, words_copy): # use itertools.izip in python2
    counter[word] += 1
    total += 1
total += sum(1 for _ in words_copy)
它最多使用On-k内存,其中n是文本中的单词数,k是文本中感兴趣的单词数。您可以使用以下方法稍微简化代码:

from itertools import zip_longest #izip_longest in python2
filtered = filter_generator(words)
total = 0
for word, _ in zip_longest(filtered, words_copy):
    counter[word] += 1
    total += 1
del counter[None]
如果生成器是恒定空间,则只使用O1内存


但是请注意,使用显式循环会降低代码的速度,因此,如果最后无法使用内存,那么为单词建立一个列表可能是更好的解决方案。

您可以简单地将u iter count的代码放入u iter\uu是的,uu iter\uu可以是一个生成器。我不明白您为什么要使其可重复,因为计数没有重置。我认为,这意味着如果在多个循环中使用它,它就会被破坏。您应该将self.\u count从类变量移到迭代器上的变量。@Veedrac谁说它是可重写的?那代码和你的完全一样。唯一的区别是它使用了一个生成器来避免定义uuuu next uuuuuuuu,但由于他定义了另一个无用的方法来实现这一点,这一点我不理解。要么定义_iter _+_下一个_,要么将_iter _定义为生成器。这不是等效的。我将在Github上主持一个代码片段,展示不同的行为。这正如一个非常Q&D的例子所提到的——我很少编写适当的迭代器,我也没有时间来编写更好的迭代器。Veedrac的答案当然好得多。你可以简单地把u itercount的代码放在里面uu iter_u是的,可以是一个生成器。我不明白你为什么要让它重复,因为计数没有重置。我认为,这意味着如果在多个循环中使用它,它就会被破坏。您应该将self.\u count从类变量移到迭代器上的变量。@Veedrac谁说它是可重写的?那代码和你的完全一样。唯一的区别是它使用了一个生成器来避免定义uuuu next uuuuuuuu,但由于他定义了另一个无用的方法来实现这一点,这一点我不理解。要么定义_iter _+_下一个_,要么将_iter _定义为生成器。这不是等效的。我将在Github上托管一个片段,显示不同的行为 我很少编写合适的迭代器,也没有时间来编写更好的迭代器。Veedrac的答案当然更好。