Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An autoincrementing callable?

I have a method within which I need to pass an ever-increasing integer to another function.

I can do this like so:

def foo(i):
    print i

def bar():

    class Incrementer(object):
        def __init__(self, start=0):
            self.i = start

        def __get__(self):
            j = self.i
            self.i += 1
            return j

    number = Incrementer()
    foo(number)
    foo(number)
    foo(number)

which correctly outputs 0 1 2 ... but I feel like I'm overlooking a much easier (or built-in) way of doing this?

like image 450
Timmy O'Mahony Avatar asked Jan 11 '12 18:01

Timmy O'Mahony


2 Answers

Try itertools.count() -- it does exactly what you need:

>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
like image 96
Sven Marnach Avatar answered Nov 02 '22 22:11

Sven Marnach


In general, if you need to retain state between one call to a function and the next, what you want is either an object (your solution) or a generator. In some cases one will be simpler than the other, but there's nothing wrong with how you've done it, in principle (though you seem to have some issues with the implementation).

Sven's suggestion, itertools.count(), is a generator. Its implementation is something like this:

def count():
    i = 0
    while True:
        yield i
        i += 1

Now, if you wanted it to be callable like a function, rather than having to do next(c), you could define a wrapper that made it so:

 def count(c=itertools.count()):
     return next(c)

Or the inevitable one-line lambda:

count = lambda c=itertools.count(): next(c)

Then count() returns the next integer each time you call it.

Of course, if you want to be able to create any number of callable functions, each with their own counter, you can write a factory for that:

def counter():
    return lambda c=itertools.count(): next(c)

Then it's:

c = counter()
print c()   # 0
print c()   # 1
# etc

This still seems simpler to me than an object, but not by much. If your state or logic were any more complex, the encapsulation of the object might win out.

like image 24
kindall Avatar answered Nov 02 '22 22:11

kindall