如何创建一个一次返回列表中的项目的函数?

时间:2015-08-17 17:20:29

标签: python function iterator generator

每次调用函数时,我都试图让我的函数逐个返回列表中的项目。我有这段代码:

def abc():
    ls = ['a', 'b', 'c']

    for i in ls:
        ls.append(i)
        yield i

我可以在终端上输入类似的内容并按住next()来获取列表中的下一个项目。

    >>>ab = abc()
    >>>next(ab)
    'a'
    >>>next(ab)
    'b'
    >>>next(ab)
    'c'
    >>>next(ab)
    'a'
    >>>next(ab)
    'b'

每次调用next时它都应该永远存在。我不想在终端中重复输入next(ab),而是每次调用函数abc()时都要让我的函数执行所有操作(返回列表中的下一项)。

4 个答案:

答案 0 :(得分:3)

基本上你正在寻找一个闭包函数:

def func():
    seq = ['a', 'b', 'c']
    ind = [-1]
    def inner():
        ind[0] += 1   
        return seq[ind[0]%len(seq)]

    return inner

>>> f = func() # One call is still required after that the
               # returned inner function can maintain the state.
>>> f()
'a'
>>> f()
'b'
>>> f()
'c'
>>> f()
'a'

在Python 3中,我们可以使用ind关键字,而不是将nonlocal定义为列表。

或使用itertools.cycle

from itertools import cycle

def func(seq):
    return cycle(seq).next
...
>>> f = func('abc')
>>> f()
'a'
>>> f()
'b'
>>> f()
'c'
>>> f()
'a'
>>> f()
'b'

答案 1 :(得分:2)

您需要chown

每次函数调用发生时

queue

这将为您提供所需的行为。

编辑:

x=[1,2,3]
k= x.pop(0)
x.append(k)
return k

答案 2 :(得分:1)

您使用的函数使用越来越多的内存,因为它会附加到每次迭代的列表中。改进是维持一个指数:

def abc():
    ls = ['a', 'b', 'c']

    i = 0;
    while True:
        yield ls[i]
        i = (i+1) % len(ls)

你所拥有的正是你所需要的。它是生成器。通常,您不会直接致电next()。通常,您将使用循环来处理生成器生成的值:

for thing in abc():
    print(thing)

由于您的生成器永远不会抛出StopIteration异常,因此for循环将永远不会结束。

答案 3 :(得分:0)

这需要创建一个更高阶的函数,它将使用闭包来创建一个辅助函数来做你想要的。

def create_wrapper(func):
    iter = func()
    def wrapper():
        return next(iter)
    return wrapper

ab = create_wrapper(abc)
ab()
>>> 'a'
ab()
>>> 'b'

等等。

以下是上述代码上下文中高阶函数和闭包的快速介绍 -

在上面的代码中,func实际上是一个函数引用,注意我们如何在abc之后没有parens的情况下调用create_wrapper(abc),所以它实际上并没有执行abc()。然后我们创建一个iter对象并创建一个名为wrapper的子函数。我们在子函数中引用iter对象,即使它是在父函数中定义的。这种用法称为闭包。当我们将函数引用返回给包装器时,create_wrapper超出范围,因此在其中使用的任何变量都应该包括iter。但是因为它在子函数中被引用,它继承了它的父级,所以它被保留了。

BTW - 通过附加到列表创建无限迭代器的方式非常聪明:-)但它显然存在内存溢出的危险。还有其他方法可以创建无限迭代器。查看https://docs.python.org/3/library/itertools.html