[英]Function for calling a function repeatedly?
Consider the hypothetical function repeatcall
, that takes as arguments a no-args callable func
and a positive integer n
, and returns a list whose members are obtained by executing func()
n
times.考虑假设的 function repeatcall
,它采用 arguments 一个无参数可调用func
和一个正数 integer n
,并返回一个列表,其成员是通过执行func()
n
次获得的。 It supports an infinite stream of silly hijinks like:它支持无限的 stream 傻笑,例如:
>>> 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]
I could swear that I've seen a function like repeatcall
somewhere in the Python 2.x standard libraries, but I can't find it.我可以发誓,我在 Python 2.x 标准库的某处看到过类似repeatcall
的 repeatcall,但我找不到它。 If I didn't dream this, where in the standard library can I find it?如果我没有想到这个,我可以在标准库中的什么地方找到它?
PS: I know it's trivial to roll one's own, but I hate to reinvent wheels, especially those are already in the standard library. PS:我知道自己动手是微不足道的,但我讨厌重新发明轮子,尤其是那些已经在标准库中的轮子。 I am not asking how to roll my own.我不是在问如何推出自己的。
Edit: made it even more explicit that I am not asking how to code repeatcall
.编辑:更明确地说我不是在问如何编写repeatcall
代码。
You've seen this in the standard library docs, not the standard library itself.您已经在标准库文档中看到了这一点,而不是标准库本身。
It's repeatfunc
from the itertools
recipes :它是itertools
食谱中的repeatfunc
:
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))
It allows arguments and should (theoretically) perform better than a list comprehension because func
only has to be looked up once.它允许 arguments 并且(理论上)应该比列表理解表现得更好,因为func
只需要查找一次。 repeat
is also faster than range
for when you're not actually using the counter.当您实际上不使用计数器时, repeat
也比range
快。
There's a reason this doesn't exist: the idiomatic way to code a function that doesn't take arguments on each invocation, and returns something new is to code it as a generator.这不存在是有原因的:编写 function 的惯用方法不会在每次调用时使用 arguments,并返回一些新的东西是将其编码为生成器。
You would then use a list comprehension or generator expression to call it as many times as you like: [next(gen) for i in xrange(5)]
.然后,您可以使用列表推导式或生成器表达式来多次调用它: [next(gen) for i in xrange(5)]
。 Better yet, gen
can itself be the result of a generator expression like (id(dict()) for i in (itertools.repeat(None)))
.更好的是, gen
本身可以是生成器表达式的结果,例如(id(dict()) for i in (itertools.repeat(None)))
。
Thus, python has no library support for this because it supports it syntactically.因此, python 没有库支持它,因为它在语法上支持它。
Do you mean something like this?:你的意思是这样的吗?:
>> from random import random
>> print [random() for x in range(5)]
[0.015015074309405185,
0.7877023608913573,
0.2940706206824023,
0.7140457069245207,
0.07868376815555878]
Seems succinct enough no?似乎足够简洁不是吗?
You can use the apply built-in function for this purpose为此,您可以使用内置的应用程序 function
>>> 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]
>>>
Note** From the manual The use of apply() is equivalent to function(*args, **keywords).注意** 从手册中 apply() 的使用等同于 function(*args, **keywords)。
So repeatcall can also be written as所以repeatcall也可以写成
>>> def repeatcall(func,n):
[func() for i in range(0,n)]
While reading comments here I realized that iter(foo, expr)
will create an infinite iterator of the result of foo
as long as it never equals expr
.在这里阅读评论时,我意识到iter(foo, expr)
将创建foo
结果的无限迭代器,只要它永远不等于expr
。
for the example in the question, iter(lambda: id(dict()), None)
will create an infinite iterator of ids of dicts.对于问题中的示例, iter(lambda: id(dict()), None)
将创建一个无限迭代器的 id 的字典。
While not a direct answer to this question, I found it useful since in my usecase I wanted it to be part of a finite zip
expression anyways and just needed the iterator to keep producing elements.虽然不是这个问题的直接答案,但我发现它很有用,因为在我的用例中我希望它无论如何都是有限zip
表达式的一部分并且只需要迭代器来继续生成元素。
hopefully this might help others that stumble upon this question希望这可以帮助其他偶然发现这个问题的人
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.