Succinctly wrap a list in a callable that returns each list element in order for each successive call

Question:

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.

Asked By: elhefe

||

Answers:

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
>>> 
Answered By: Tom Karzes

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
Answered By: rdas

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)
Answered By: Andrej Kesely
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.