7

考虑假设函数repeatcall,它接受一个无参数可调用func和一个正整数作为参数n,并返回一个列表,其成员是通过执行func() n时间获得的。它支持无限的愚蠢hijinks流,例如:

>>> repeatcall(lambda: id(dict()), 5)
[45789920, 45788064, 45807216, 45634816, 45798640]

>>> urandom = lambda: struct.unpack('Q', open('/dev/urandom').read(8))[0]
>>> repeatcall(urandom, 3)
[3199039843823449742, 14990726001693341311L, 11583468019313082272L]

>>> class Counter(itertools.count): __call__ = itertools.count.next
>>> repeatcall(Counter(100, -2), 4)
[100, 98, 96, 94]

我可以发誓我repeatcall在 Python 2.x 标准库中的某个地方看到过类似的函数,但我找不到它。如果我没有想到这个,我在标准库的哪里可以找到它?

PS:我知道自己动手是微不足道的,但我讨厌重新发明轮子,尤其是那些已经在标准库中的。我不是在问如何自己动手。

编辑:更明确地说我不是在问如何编码repeatcall

4

5 回答 5

14

您已经在标准库文档中看到了这一点,而不是标准库本身。

repeatfunc来自itertools食谱

def repeatfunc(func, times=None, *args):
    """Repeat calls to func with specified arguments.

    Example:  repeatfunc(random.random)
    """
    if times is None:
        return starmap(func, repeat(args))
    return starmap(func, repeat(args, times))

它允许参数并且应该(理论上)比列表理解执行得更好,因为func只需要查找一次。repeat也比range您不实际使用计数器时更快。

于 2012-04-06T20:42:49.597 回答
4

这不存在是有原因的:编写一个在每次调用时不接受参数并返回新内容的函数的惯用方法是将其编码为生成器。

然后,您可以使用列表推导式或生成器表达式任意多次调用它:[next(gen) for i in xrange(5)]. 更好的是,gen它本身可以是生成器表达式的结果,例如(id(dict()) for i in (itertools.repeat(None))).

因此,python 对此没有库支持,因为它在语法上支持它。

于 2012-04-07T07:38:33.803 回答
3

你的意思是这样的吗?:

>> from random import random
>> print [random() for x in range(5)]
[0.015015074309405185,
 0.7877023608913573,
 0.2940706206824023,
 0.7140457069245207,
 0.07868376815555878]

看起来够简洁了吧?

于 2012-04-06T20:39:37.810 回答
2

为此,您可以使用apply内置函数

>>> def repeatcall(func,n):
    [apply(func) for i in range(0,n)]

>>> repeatcall(lambda: id(dict()), 5)
[56422096, 56422240, 56447024, 56447168, 56447312]

>>> import itertools
>>> class Counter(itertools.count): __call__ = itertools.count.next

>>> repeatcall(Counter(100, -2), 4)
[100, 98, 96, 94]
>>> 

注意**来自手册 apply() 的使用等同于 function(*args, **keywords)。

所以repeatcall也可以写成

>>> def repeatcall(func,n):
    [func() for i in range(0,n)]
于 2012-04-06T20:39:56.643 回答
0

在这里阅读评论时,我意识到这iter(foo, expr)将创建一个无限迭代器的结果,foo只要它从不等于expr

对于问题中的示例,iter(lambda: id(dict()), None)将创建 dicts 的无限迭代器。

虽然不是这个问题的直接答案,但我发现它很有用,因为在我的用例中我希望它成为有限zip表达式的一部分,并且只需要迭代器来继续生成元素。

希望这可以帮助其他偶然发现这个问题的人

于 2021-12-29T16:29:57.000 回答