I feel like I must be missing something obvious, but I can't seem to find a succinct way of creating a a callable that returns elements of a list in order for each call. E.g.
In [1]: class CallableList:
...: def __init__(self, list_):
...: self.list = list_
...: self.pos = -1
...: def __call__(self):
...: self.pos = 1
...: return self.list[self.pos]
...:
In [2]: x = CallableList([5, 7, 2])
In [3]: x()
Out[3]: 5
In [4]: x()
Out[4]: 7
In [5]: x()
Out[5]: 2
... but without a class.
A generator (which is where my mind first went) isn't callable so that doesn't seem to work, unless I'm missing something.
CodePudding user response:
You can use iter()
to obtain an iterator for a list. You can then use next()
to obtain successive elements. For example:
>>> x = [1, 2, 3]
>>> r = iter(x)
>>> next(r)
1
>>> next(r)
2
>>> next(r)
3
>>>
This is almost what you requested, but not quite, since you need to provide r
as an argument to next
.
To make a callable, you can can wrap it in a lambda
:
>>> x = [1, 2, 3]
>>> r = iter(x)
>>> c = lambda: next(r)
>>> c()
1
>>> c()
2
>>> c()
3
>>>
CodePudding user response:
Here's a solution using a closure with function attributes:
def callable_list(param):
def f():
if not hasattr(f, 'iter'):
f.iter = iter(param)
return next(f.iter)
return f
x = callable_list([5, 7, 2])
print(x())
print(x())
print(x())
result:
5
7
2
CodePudding user response:
A slight modification off @TomKarzes anwer, wrap the iter()
/next()
to a function:
def CallableList(lst):
i = iter(lst)
return lambda: next(i)
x = CallableList([5, 7, 2])
print(x())
print(x())
print(x())
Prints:
5
7
2
Or one-liner:
CallableList = lambda lst: lambda _i=iter(lst): next(_i)