简体   繁体   English

python:函数的迭代器

[英]python: iterator from a function

What is an idiomatic way to create an infinite iterator from a function? 从函数创建无限迭代器的惯用方法是什么? For example 例如

from itertools import islice
import random
rand_characters = to_iterator( random.randint(0,256) )
print ' '.join( islice( rand_characters, 100))

would produce 100 random numbers 会产生100个随机数

You want an iterator which continuously yields values until you stop asking it for new ones? 你想要一个迭代器,它不断产生值,直到你不再要求新的值? Simply use 简单地使用

it = iter(function, sentinel)

which calls function() for each iteration step until the result == sentinel . 它为每个迭代步骤调用function() ,直到result == sentinel

So choose a sentinel which can never be returned by your wanted function, such as None , in your case. 因此,在您的情况下,选择一个永远不会被您想要的函数返回的标记,例如None

rand_iter = lambda start, end: iter(random.randint(start, end), None)
rand_bytes = rand_iter(0, 256)

If you want to monitor some state on your machine, you could do 如果要监视计算机上的某些状态,可以这样做

iter_mystate = iter(getstate, None)

which, in turn, infinitely calls getstate() for each iteration step. 反过来,它为每个迭代步骤无限调用getstate()

But beware of functions returning None as a valid value! 但要注意将None作为有效值返回的函数! In this case, you should choose a sentinel which is guaranteed to be unique, maybe an object created for exactly this job: 在这种情况下,您应该选择一个保证唯一的标记,也许是为这个作业创建的对象:

iter_mystate = iter(getstate, object())

Every time I see iter with 2 arguments, I need to scratch my head an look up the documentation to figure out exactly what is going on. 每次看到iter以2个参数,我需要帮我头上的查找的文档,弄清楚到底是怎么回事。 Simply because of that, I would probably roll my own: 正因为如此,我可能会自己动手:

def call_forever(callback):
    while True:
        yield callback()

Or, as stated in the comments by Jon Clements, you could use the itertools.repeatfunc recipe which allows you to pass arguments to the function as well: 或者,正如Jon Clements的评论中所述,您可以使用itertools.repeatfunc配方,它允许您将参数传递给函数:

import itertools as it
def repeatfunc(func, times=None, *args):
    """
    Repeat calls to func with specified arguments.
    Example:  repeatfunc(random.random)
    """
    if times is None:
        return it.starmap(func, it.repeat(args))
    return it.starmap(func, it.repeat(args, times))

Although I think that the function signature def repeatfunc(func,times=None,*args) is a little awkward. 虽然我认为函数签名def repeatfunc(func,times=None,*args)有点尴尬。 I'd prefer to pass a tuple as args (it seems more explicit to me, and "explicit is better than implicit"): 我更喜欢将一个元组作为args传递(对我来说似乎更明确,“显式优于隐式”):

import itertools as it
def repeatfunc(func, args=(),times=None):
    """
    Repeat calls to func with specified arguments.
    Example:  repeatfunc(random.random)
    """
    if times is None:
        return it.starmap(func, it.repeat(args))
    return it.starmap(func, it.repeat(args, times))

which allows it to be called like: 允许它被称为:

repeatfunc(func,(arg1,arg2,...,argN),times=4) #repeat 4 times
repeatfunc(func,(arg1,arg2,...))                #repeat infinitely

instead of the vanilla version from itertools : 而不是来自itertools的vanilla版本:

repeatfunc(func,4,arg1,arg2,...)    #repeat 4 times
repeatfunc(func,None,arg1,arg2,...) #repeat infinitely

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM