Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple number generator [closed]

How do I write a function that simply returns incrementing numbers on each call?

print counter() # 0
print counter() # 1
print counter() # 2
print counter() # 3
etc

For clarity, I'm not looking for a generator (although the answer would probably use it). The function should return an integer, not an iterable object. I'm also NOT looking for a solution involving global or otherwise shared variables (classes, function attribute etc).

See here http://www.valuedlessons.com/2008/01/monads-in-python-with-nice-syntax.html for some useful insights about the matter.

like image 405
georg Avatar asked Jan 22 '26 17:01

georg


2 Answers

You don't need to implement that function -- it already exists:

counter = itertools.count().next

or in Python 3.x

counter = itertools.count().__next__

More generally, if you want a callable that has additional state, there are several solutions:

  1. A class:

    class Counter(object):
        def __init__(self, start=0):
            self.count = 0
        def __call__(self):
            val = self.count
            self.count += 1
            return val
    
  2. A mutable default argument:

    def counter(_count=[0]):
        val = _count[0]
        _count[0] += 1
        return val
    
  3. A closure:

    def make_counter(start=0):
        count = [start]
        def counter():
            val = count[0]
            count[0] += 1
            return val
        return counter
    

    In Python 3.x, you wouldn't need the above hack using a list any more, since you could use a nonlocal declaration:

    def make_counter(start=0):
        count = start
        def counter():
            nonlocal count
            val = count
            count += 1
            return val
        return counter
    
  4. Function arguments:

    def counter():
        val = counter.count
        counter.count += 1
        return val
    counter.count = 0
    
  5. A generator:

    def count(start=0):
        while True:
            yield start
            start += 1
    counter = count().next   ## or .__next__ in Python 3.x
    

Of course all these solution have to store the current count somewhere.

like image 82
Sven Marnach Avatar answered Jan 25 '26 05:01

Sven Marnach


In short,

from itertools import count
counter = lambda c=count(): next(c)
like image 38
glglgl Avatar answered Jan 25 '26 07:01

glglgl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!