W Perl 5.10, mogę powiedzieć:Czy w Pythonie występują zmienne "stan" Perla 5.10?
sub foo() {
state $x = 1;
say $x++;
}
foo();
foo();
foo();
... i będzie wydrukować:
1
2
3
Czy Python mieć coś takiego?
W Perl 5.10, mogę powiedzieć:Czy w Pythonie występują zmienne "stan" Perla 5.10?
sub foo() {
state $x = 1;
say $x++;
}
foo();
foo();
foo();
... i będzie wydrukować:
1
2
3
Czy Python mieć coś takiego?
Najbliższa równoległość prawdopodobnie polega na dołączeniu wartości do samej funkcji.
def foo():
foo.bar = foo.bar + 1
foo.bar = 0
foo()
foo()
foo()
print foo.bar # prints 3
Tak, choć trzeba zadeklarować zmienną globalną najpierw, zanim zostanie napotkany w foo
:
x = 0
def foo():
global x
x += 1
print x
foo()
foo()
foo()
EDIT: W odpowiedzi na komentarz, to prawda, że pyton nie ma zmiennych statycznych scoped wewnątrz funkcji. Zauważ, że x
w tym przykładzie jest wyświetlany jako globalny tylko dla reszty modułu. Załóżmy na przykład, że powyższy kod znajduje się pod numerem test.py
. Załóżmy teraz piszesz następujący moduł:
from test import foo
x = 100
foo()
foo()
wyjście będzie tylko 1
i 2
nie 101
i 102
.
Nie to samo, ponieważ zmienna nie ma zasięgu wewnątrz funkcji - jest narażona na resztę kodu. – Arkady
Tak, masz rację. Python nie ma zmiennych statycznych, więc jest to jedyny sposób na zrobienie tego bez przechodzenia przez trasę klasy. Należy jednak zauważyć, że jest to narażone tylko na reszta modułu jako globalna. –
Zmienne stanu są leksykalne, a nie globalne (co jest ich głównym punktem, czymś, co przypomina globalne, które "pamięta", ale bez wad tego, że jest rzeczywistą globalnością). –
Klasa może być lepiej pasuje tutaj (i to zazwyczaj lepiej pasuje do niczego z udziałem "stan"):
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()
Python posiada generatory, które coś podobnego:
Można również użyć czegoś takiego, jak:
def static_num2():
k = 0
while True:
k += 1
yield k
static = static_num2().next
for i in range(0,10) :
print static()
, aby uniknąć globalnego var. Podniesione z this link o tym samym pytaniu.
Nie wiem, czy to jest to, czego szukasz, ale Python posiada funkcje generator, który nie zwraca wartości per se, ale obiekt generator, który generuje nową wartość za każdym
def gen():
x = 10
while True:
yield x
x += 1
wykorzystanie:
>>> a = gen()
>>> a.next()
10
>>> a.next()
11
>>> a.next()
12
>>> a.next()
13
>>>
wygląd tutaj, aby uzyskać więcej wyjaśnień na yield:
What does the "yield" keyword do in Python?
>>> def foo():
x = 1
while True:
yield x
x += 1
>>> z = iter(foo())
>>> next(z)
1
>>> next(z)
2
>>> next(z)
3
Nie, że jestem polecając to, ale tylko dla zabawy:
def foo(var=[1]):
print var[0]
var[0] += 1
Działa to ze względu na way mutable default arguments pracy w Pythonie.
Oto jeden sposób, aby wdrożyć zamknięcie w Pythonie:
def outer():
a = [4]
def inner():
print a[0]
a[0] = a[0] + 1
return inner
fn = outer()
fn() # => 4
fn() # => 5
fn() # => 6
Pożyczyłem ten przykład verbatim z python mailing list post.
Oto kolejny brudny tani sposób, aby to zrobić, jest to wariacja na odpowiedź Tryiptich, ale używając dekoratorów
def static_var(name, value):
def dec(function):
setattr(function, name, value)
return function
return dec
@static_var('counter', 0)
def counting_function():
counting_function.counter = counting_function.counter + 1
print counting_function.counter
"""
>>> counting_function()
1
>>> counting_function()
2
>>> counting_function()
3
>>> counting_function()
4
>>> counting_function()
5
>>>
"""
Aby pytonować fanów: Należy zauważyć, że zmienne stanu nie są używane tylko dla generatorów w Perlu. Są wygodnym sposobem na enkapsulowanie informacji, które muszą przetrwać z pewną funkcją przez całe życie. :) –