如何制作一个将 return 列表中的项目一次一个的函数?
How to make a function that will return items in a list one at a time?
我试图在每次调用函数时将我的函数return项逐一添加到列表中。我有这个代码:
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()
时都执行所有操作(return 列表中的下一项)。
您需要 queue
.
每次函数调用发生
x=[1,2,3]
k= x.pop(0)
x.append(k)
return k
这将使您获得所需的行为。
编辑:
ls = ['a', 'b', 'c']
def abc():
k= ls.pop(0)
ls.append(k)
return k
print abc()
print abc()
print abc()
print abc()
print abc()
您的函数使用越来越多的内存,因为它会在每次迭代时追加到列表中。一个改进是维护一个索引:
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 循环永远不会结束。
基本上你在寻找一个闭包函数:
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 中,我们可以使用 nonlocal
关键字而不是将 ind
定义为列表。
或使用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'
这需要创建一个高阶函数,该函数将使用闭包创建一个辅助函数来执行您想要的操作。
def create_wrapper(func):
iter = func()
def wrapper():
return next(iter)
return wrapper
ab = create_wrapper(abc)
ab()
>>> 'a'
ab()
>>> 'b'
以此类推
这里是对上述代码上下文中高阶函数和闭包的快速介绍 -
在上面的代码中,func实际上是一个函数引用,注意我们调用create_wrapper(abc)时没有在abc后面加上括号,所以它实际上并不是在执行abc()。然后我们创建一个 iter 对象并创建一个名为 wrapper 的子函数。我们在子函数中引用 iter 对象,即使它是在父函数中定义的。这种用法称为闭包。当我们 return 对包装器的函数引用时, create_wrapper 超出范围,其中使用的任何变量也应该超出范围 - 包括 iter。但是因为它在其父函数之外的子函数中被引用,所以 iter 被保留了。
顺便说一句 - 通过附加到列表来创建无限迭代器的方式非常聪明 :-) 但它显然存在内存溢出的危险。还有其他方法可以创建无限迭代器。查看 https://docs.python.org/3/library/itertools.html。
我试图在每次调用函数时将我的函数return项逐一添加到列表中。我有这个代码:
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()
时都执行所有操作(return 列表中的下一项)。
您需要 queue
.
每次函数调用发生
x=[1,2,3]
k= x.pop(0)
x.append(k)
return k
这将使您获得所需的行为。
编辑:
ls = ['a', 'b', 'c']
def abc():
k= ls.pop(0)
ls.append(k)
return k
print abc()
print abc()
print abc()
print abc()
print abc()
您的函数使用越来越多的内存,因为它会在每次迭代时追加到列表中。一个改进是维护一个索引:
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 循环永远不会结束。
基本上你在寻找一个闭包函数:
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 中,我们可以使用 nonlocal
关键字而不是将 ind
定义为列表。
或使用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'
这需要创建一个高阶函数,该函数将使用闭包创建一个辅助函数来执行您想要的操作。
def create_wrapper(func):
iter = func()
def wrapper():
return next(iter)
return wrapper
ab = create_wrapper(abc)
ab()
>>> 'a'
ab()
>>> 'b'
以此类推
这里是对上述代码上下文中高阶函数和闭包的快速介绍 -
在上面的代码中,func实际上是一个函数引用,注意我们调用create_wrapper(abc)时没有在abc后面加上括号,所以它实际上并不是在执行abc()。然后我们创建一个 iter 对象并创建一个名为 wrapper 的子函数。我们在子函数中引用 iter 对象,即使它是在父函数中定义的。这种用法称为闭包。当我们 return 对包装器的函数引用时, create_wrapper 超出范围,其中使用的任何变量也应该超出范围 - 包括 iter。但是因为它在其父函数之外的子函数中被引用,所以 iter 被保留了。
顺便说一句 - 通过附加到列表来创建无限迭代器的方式非常聪明 :-) 但它显然存在内存溢出的危险。还有其他方法可以创建无限迭代器。查看 https://docs.python.org/3/library/itertools.html。