Автоинкрементный вызов? - PullRequest
7 голосов
/ 11 января 2012

У меня есть метод, в рамках которого мне нужно передать постоянно увеличивающееся целое число в другую функцию.

Я могу сделать это так:

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)

, который правильно выводит 0 1 2 ..., но мне кажется, что я упускаю гораздо более простой (или встроенный) способ сделать это?

Ответы [ 2 ]

14 голосов
/ 11 января 2012

Попробуйте itertools.count() - он делает именно то, что вам нужно:

>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
7 голосов
/ 11 января 2012

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

Предложение Свена, itertools.count(), является генератором. Его реализация выглядит примерно так:

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

Теперь, если вы хотите, чтобы он вызывался как функция, а не next(c), вы можете определить оболочку, которая сделает это так:

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

Или неизбежная однострочная лямбда:

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

Затем count() возвращает следующее целое число каждый раз, когда вы его вызываете.

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

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

Тогда это:

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

Это все еще кажется мне проще, чем предмет, но ненамного. Если бы ваше состояние или логика были более сложными, инкапсуляция объекта могла бы победить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...