2012-03-07 4 views
-1

Как написать функцию, которая просто возвращает инкрементирующие числа для каждого вызова?Генератор простых чисел

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

Для ясности я не ищу генератор (хотя ответ, вероятно, будет его использовать). Функция должна возвращать целое число, а не итерируемый объект. Я также НЕ ищу решение, включающее глобальные или другие общие переменные (классы, атрибут функции и т. Д.).

См. Здесь http://www.valuedlessons.com/2008/01/monads-in-python-with-nice-syntax.html для получения полезной информации по этому вопросу.

+3

Вам нужно будет хранить где-то последний использованный номер для увеличения. Без использования глобальных общих переменных и т. Д. Единственным решением было бы передать последнее число, где счетчик возвращает это значение + 1, но это вряд ли называется решением. –

+1

Вам нужно сохранить информацию * где-то *, в противном случае то, что вы предлагаете, невозможно. – rumpel

+0

Это домашнее задание? Для чего вы используете счетчик? –

ответ

1

Короче говоря,

from itertools import count 
counter = lambda c=count(): next(c) 
+1

Есть ли причина использовать это над 'count(). Next'? –

+2

Лямбда - ненужное неправильное направление. –

+0

@S Возможно, но AFAICT делает его переносимым между Py2 и 3 – glglgl

10

Вам не нужно реализовать эту функцию - она ​​уже существует:

counter = itertools.count().next 

или Python 3.x

counter = itertools.count().__next__ 

Вообще, если вы хотите, вызываемым, что имеет дополнительное состояние, существует несколько решений:

  1. A c деваха:

    class Counter(object): 
        def __init__(self, start=0): 
         self.count = 0 
        def __call__(self): 
         val = self.count 
         self.count += 1 
         return val 
    
  2. Изменяемый аргумент по умолчанию:

    def counter(_count=[0]): 
        val = _count[0] 
        _count[0] += 1 
        return val 
    
  3. Затвор:

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

    В Python 3.x, вам не нужен выше хак с использованием списка более того, поскольку вы можете использовать заявление nonlocal:

    def make_counter(start=0): 
        count = start 
        def counter(): 
         nonlocal count 
         val = count 
         count += 1 
         return val 
        return counter 
    
  4. Аргументы функции:

    def counter(): 
        val = counter.count 
        counter.count += 1 
        return val 
    counter.count = 0 
    
  5. генератора:

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

Конечно все эти решения должны сохранить текущее количество где-то.

+1

Обратите внимание, что 1 и 3 используют состояние экземпляра, но 2 и 4 используют общее состояние. –

+0

@ thg435: Вы запросили функцию с состоянием без использования состояния. Вы правы, я этого не делал. В чем смысл этого ограничения? Это не имеет смысла. –

+0

@ thg435: И предложение itertools не является закрытием. Это связанный метод объекта count. –

4

Итак, вы хотите написать функцию, которая делает магию, не используя какие-либо функции языка, не так ли? Это чепуха. Вы либо пишете генератор, либо делаете вызываемый класс (атрибуты экземпляра ничем не «разделяются»).

class Counter(object): 
    def __init__(self): 
     self.n = -1 
    def __call__(self): 
     self.n += 1 
     return self.n 

counter = Counter() 
counter() # 0 
# ... 

# generator 
def counter(): 
    n = 0 
    while True: 
     yield n 
     n += 1 
Смежные вопросы