Есть ли у Python что-то вроде переменных состояния Perl 5.10? - PullRequest
8 голосов
/ 03 марта 2009

В Perl 5.10 я могу сказать:

sub foo () {
  state $x = 1;
  say $x++;
}

foo();
foo();
foo();

... и он распечатает:

1
2
3

Есть ли у Python что-то подобное?

Ответы [ 11 ]

17 голосов
/ 03 марта 2009

Класс может быть лучше подходит здесь (и обычно лучше подходит для всего, что связано с "состоянием"):

class Stateful(object):

    def __init__(self):
        self.state_var = 0

    def __call__(self):
        self.state_var = self.state_var + 1
        print self.state_var

foo = Stateful()
foo()
foo()
12 голосов
/ 03 марта 2009

Ближайшая параллель - это, вероятно, присвоение значений самой функции.

def foo():
    foo.bar = foo.bar + 1

foo.bar = 0

foo()
foo()
foo()

print foo.bar # prints 3
9 голосов
/ 03 марта 2009

В Python есть генераторы, которые делают что-то похожее:

Что делает ключевое слово yield в Python?

8 голосов
/ 03 марта 2009

Не уверен, что это то, что вы ищете, но в Python есть функции генератора, которые не возвращают само значение, но объект генератора, который генерирует новое значение каждый раз

def gen():
   x = 10
   while True:
      yield x
      x += 1

использование:

>>> a = gen()
>>> a.next()
10
>>> a.next()
11
>>> a.next()
12
>>> a.next()
13
>>> 

смотрите здесь для более подробного объяснения yield :
Что делает ключевое слово yield в Python?

5 голосов
/ 03 марта 2009

Вот один из способов реализации замыкания в python:

def outer():
    a = [4]
    def inner():
        print a[0]
        a[0] = a[0] + 1
    return inner

fn = outer()
fn() # => 4
fn() # => 5
fn() # => 6

Я дословно заимствовал этот пример из сообщения списка рассылки python .

2 голосов
/ 03 марта 2009

Предпочтительным способом является использование класса или генератора (yield).

Для полноты вот вариант с закрытием в Python 3.x:

>>> def make_foo():
...     x = 1
...     def foo():
...         nonlocal x
...         print(x)
...         x += 1
...     return foo
...
>>> foo = make_foo()
>>> foo()
1
>>> foo()
2
>>> foo()
3
2 голосов
/ 03 марта 2009

Не то, чтобы я рекомендовал это, но просто для удовольствия:

def foo(var=[1]):
    print var[0]
    var[0] += 1

Это работает из-за изменяемых по умолчанию аргументов в Python.

2 голосов
/ 03 марта 2009

Вы также можете использовать что-то вроде

def static_num2():
    k = 0
    while True:
        k += 1
        yield k

static = static_num2().next

for i in range(0,10) :
    print static()

, чтобы избежать глобальной переменной. Снял с эту ссылку о том же вопросе.

2 голосов
/ 03 марта 2009

Да, хотя вы должны сначала объявить глобальную переменную, прежде чем она встретится в foo:

x = 0

def foo():
    global x
    x += 1
    print x

foo()
foo()
foo()

РЕДАКТИРОВАТЬ: В ответ на комментарий, это правда, что Python не имеет статических переменных, ограниченных в функции. Обратите внимание, что x в этом примере предоставляется только как остальная часть модуля как глобальная. Например, скажем, код выше находится в test.py. Теперь предположим, что вы пишете следующий модуль:

from test import foo
x = 100
foo()
foo()

Вывод будет только 1 и 2, а не 101 и 102.

1 голос
/ 03 марта 2009
>>> def foo():
    x = 1
    while True:
        yield x
        x += 1


>>> z = iter(foo())
>>> next(z)
1
>>> next(z)
2
>>> next(z)
3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...