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?
Try itertools.count()
-- it does exactly what you need:
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With