807 Stimmen

Was ist die Python-Entsprechung von statischen Variablen innerhalb einer Funktion?

Was ist die idiomatische Python-Entsprechung für diesen C/C++-Code?

void foo()
{
    static int counter = 0;
    counter++;
    printf("counter is %d\n", counter);
}

Wie implementiert man das statische Mitglied auf der Funktionsebene, im Gegensatz zur Klassenebene? Und ändert sich etwas, wenn man die Funktion in eine Klasse einordnet?

33 Stimmen

Es gibt NO Gleichwertigkeit, fürchte ich. Selbst wenn man den Decorator-Hack mit Funktionsattributen durchführt, kann man auf die Variable von außen zugreifen, was den Sinn der Sache leider zunichte macht. Außerdem müssen Sie den Funktionsnamen in der Funktion hart codieren, was sehr ärgerlich ist. Ich würde vorschlagen, stattdessen globale Variablen einer Klasse oder eines Moduls zu verwenden, mit der konventionellen _ Vorwahl.

17 Stimmen

Für Nicht-C-Programmierer, [ [stackoverflow.com/questions/5033627/](https://stackoverflow.com/questions/5033627/static-variable-inside-of-a-function-in-c#5033656](a "static variable inside of a function in c%235033656%5d(a") statische Variable innerhalb einer Funktion ist nur innerhalb des Funktionsbereichs dieser Funktion sichtbar, aber ihre Lebensdauer ist die gesamte Lebensdauer des Programms, und sie wird nur einmal initialisiert). Im Grunde genommen handelt es sich um einen dauerhaften Zähler oder eine Speichervariable, die zwischen Funktionsaufrufen lebt.

2 Stimmen

@lpapp: Irgendwie schon, es ist ein Klassenmitglied . Sie haben Recht, dass wir nicht verhindern können, dass andere Codes sie anzeigen oder ändern.

5voto

Teddy Punkte 5763

Le site idiomatisch Weg ist die Verwendung eines Klasse die Attribute haben können. Wenn die Instanzen nicht getrennt sein sollen, verwenden Sie ein Singleton.

Es gibt eine Reihe von Möglichkeiten, wie man "statische" Variablen in Python fälschen oder einschmuggeln kann (eine bisher nicht erwähnte Möglichkeit ist, ein veränderbares Standardargument zu haben), aber dies ist nicht die Pythonisch, idiomatisch Weise zu tun. Verwenden Sie einfach eine Klasse.

Oder möglicherweise ein Generator, wenn Ihr Nutzungsmuster passt.

0 Stimmen

Bei eigenständigen rekursiven Funktionen wird die default ist das eleganteste Argument.

5voto

Richard Merren Punkte 41

Eine globale Deklaration bietet diese Funktionalität. In dem folgenden Beispiel (Python 3.5 oder höher, um das "f" zu verwenden), wird die Zähler Variable außerhalb der Funktion definiert ist. Die Definition als global in der Funktion bedeutet, dass die "globale" Version außerhalb der Funktion für die Funktion verfügbar gemacht werden soll. Jedes Mal, wenn die Funktion ausgeführt wird, ändert sie also den Wert außerhalb der Funktion und behält ihn über die Funktion hinaus bei.

counter = 0

def foo():
    global counter
    counter += 1
    print("counter is {}".format(counter))

foo() #output: "counter is 1"
foo() #output: "counter is 2"
foo() #output: "counter is 3"

0 Stimmen

Das funktioniert bei richtiger Anwendung genauso. Der Unterschied zum C-Code besteht darin, dass im C-Beispiel des Autors die Zählervariable nur von der Funktion berührt werden konnte. Eine globale Variable in Python kann überall im Skript verwendet oder geändert werden

4voto

lost Punkte 1857

Eine weitere (nicht empfohlene!) Abwandlung des Callable Objects wie https://stackoverflow.com/a/279598/916373 Wenn es Ihnen nichts ausmacht, eine ausgefallene Anrufsignatur zu verwenden, könnten Sie Folgendes tun

class foo(object):
    counter = 0;
    @staticmethod
    def __call__():
        foo.counter += 1
        print "counter is %i" % foo.counter

>>> foo()()
counter is 1
>>> foo()()
counter is 2

4voto

Feca Punkte 41

Seelenwanderung n +=1

def foo():
  foo.__dict__.setdefault('count', 0)
  foo.count += 1
  return foo.count

4voto

Miguel Angelo Punkte 23208

Verwendung eines Dekorators und eines Abschlusses

Der folgende Dekorator kann verwendet werden, um statische Funktionsvariablen zu erstellen. Er ersetzt die deklarierte Funktion durch die Rückgabe von sich selbst. Dies impliziert, dass die dekorierte Funktion eine Funktion zurückgeben muss.

def static_inner_self(func):
    return func()

Dann verwenden Sie den Dekorator auf eine Funktion, die eine andere Funktion mit einer erfassten Variablen zurückgibt:

@static_inner_self
def foo():
    counter = 0
    def foo():
        nonlocal counter
        counter += 1
        print(f"counter is {counter}")
    return foo

nonlocal erforderlich, andernfalls denkt Python, dass die counter Variable ist eine lokale Variable und keine erfasste Variable. Python verhält sich so aufgrund der Variablenzuweisung counter += 1 . Jede Zuweisung in einer Funktion lässt Python glauben, dass die Variable lokal ist.

Wenn Sie der Variablen in der inneren Funktion nichts zuweisen, können Sie das Feld nonlocal Anweisung, zum Beispiel, in dieser Funktion verwende ich, um Zeilen einer Zeichenkette einzurücken, wobei Python ableiten kann, dass die Variable nonlocal :

@static_inner_self
def indent_lines():
    import re
    re_start_line = re.compile(r'^', flags=re.MULTILINE)
    def indent_lines(text, indent=2):
        return re_start_line.sub(" "*indent, text)
    return indent_lines

P.S. Es gibt eine gelöschte Antwort, die das Gleiche vorschlägt. Ich weiß nicht, warum der Autor sie gelöscht hat. https://stackoverflow.com/a/23366737/195417

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X