“final”-Schlüsselwortäquivalent für Variablen in Python?

Lesezeit: 7 Minuten

Benutzer-Avatar
Jason Coon

Ich konnte keine Dokumentation zu einem Äquivalent von Java finden final in Python, gibt es so etwas?

Ich erstelle eine Momentaufnahme eines Objekts (wird zur Wiederherstellung verwendet, falls etwas fehlschlägt); Sobald diese Backup-Variable zugewiesen ist, sollte sie nicht mehr geändert werden – ein Final-ähnliches Feature in Python wäre dafür nett.

  • mögliches Duplikat von Konstante in Python erstellen

    – Anderson Green

    28. Februar 2014 um 20:51 Uhr

  • Insgesamt … ist der Mangel an Unveränderlichkeit katastrophal … beweist, dass Python nicht für groß angelegte Multithread-Apps geeignet ist.

    – Apurva Singh

    7. Dezember 2017 um 13:09 Uhr

  • @ApurvaSingh Ich stimme zwar zu, dass Python dafür nicht geeignet ist, aber es gibt Tupel und Frozenset in der Standardbibliothek und MagicStack/Unveränderliche ist eine Implementierung eines änderbaren Mappings, das ebenfalls zur Standardbibliothek hinzugefügt werden soll.

    – Antonagestam

    14. September 2019 um 8:26 Uhr

Benutzer-Avatar
Stefan202

Es gibt kein final Äquivalent in Python.

Um jedoch schreibgeschützte Felder von Klasseninstanzen zu erstellen, können Sie die verwenden Eigentum Funktion.

Bearbeiten: Vielleicht möchten Sie so etwas:

class WriteOnceReadWhenever:
    def __setattr__(self, attr, value):
        if hasattr(self, attr):
            raise Exception("Attempting to alter read-only value")

        self.__dict__[attr] = value

  • Ich ersetze immer self.__dict__[attr] = value mit return super(WriteORW, self).__setattr__(attr, value)

    – John Strood

    11. Januar 2019 um 8:44 Uhr

Eine Variable in Java sein final bedeutet im Grunde, dass Sie, nachdem Sie eine Variable zugewiesen haben, diese Variable nicht mehr neu zuweisen dürfen, um auf ein anderes Objekt zu zeigen. Es bedeutet eigentlich nicht, dass das Objekt nicht geändert werden kann. Der folgende Java-Code funktioniert beispielsweise einwandfrei:

public final List<String> messages = new LinkedList<String>();

public void addMessage()
{
    messages.add("Hello World!");  // this mutates the messages list
}

aber das Folgende würde nicht einmal kompilieren:

public final List<String> messages = new LinkedList<String>();

public void changeMessages()
{
    messages = new ArrayList<String>();  // can't change a final variable
}

Ihre Frage bezieht sich also darauf, ob final existiert in Python. Es tut nicht.

Allerdings hat Python unveränderliche Datenstrukturen. Während Sie beispielsweise a mutieren können listdu kannst a nicht mutieren tuple. Sie können a mutieren set aber nicht ein frozensetetc.

Mein Rat wäre, sich einfach keine Gedanken über die Durchsetzung der Nicht-Mutation auf Sprachebene zu machen und sich einfach darauf zu konzentrieren, sicherzustellen, dass Sie keinen Code schreiben, der diese Objekte mutiert, nachdem sie zugewiesen wurden.

  • In Java zeigt eine nicht primitive Variable auf ein Objekt. Wenn Sie eine Variable als final bezeichnen, können Sie die Variable nicht auf ein anderes Objekt zeigen lassen, aber das Objekt, auf das gezeigt wird, kann mutiert werden.

    – IceArdor

    17. Februar 2015 um 18:49 Uhr

  • Es gibt eine andere Verwendung für final in Java, ich denke, dass es dasselbe ist wie static in C++, und das heißt, dass die Codezeile, die einer finalen Variablen zuweist, nicht mehr als einmal ausgeführt wird, selbst wenn sie innerhalb einer Funktion deklariert wird. Es ermöglicht Ihnen, die Variable vor dem Rest des Codes zu verbergen, ohne jedes Mal, wenn die Funktion aufgerufen wird, ständig neue Instanzen zu erstellen. In Python müssen Sie eine Variable im globalen Bereich verwenden oder die Kosten für das ständige Erstellen neuer Instanzen in Kauf nehmen. cpp.sh/24gj

    – Hatoru Hansou

    5. November 2015 um 3:08 Uhr


  • Ich finde es eine schreckliche Empfehlung simply concentrate on making sure that you don't write any code which mutates these objects after they're assigned. Wie werden Sie dies anderen Menschen mitteilen? Oder an dein zukünftiges Ich? Mit einem Kommentar oder Docstring? Ein formales Sprachkonstrukt ist viel weniger flüchtig als ein Kommentar. Python, dem dies fehlt, ist in der Tat besorgniserregend.

    – delucasvb

    7. Januar 2019 um 14:13 Uhr

  • Nicht mehr korrekt für Versionen >= 3.8. Siehe die Antwort von @congusbongus unten.

    – Karl Merriam

    2. November 2019 um 21:38 Uhr

  • Nachdem Sie alle Antworten und Witze von “Python-Experten” über das Deklarieren von Konstanten gelesen haben, sieht es so aus, als ob Python für “Einzelentwicklerprojekt” ist.

    – Tristan

    17. August um 16:22 Uhr

Benutzer-Avatar
congusbongus

Python 3.8 (über PEP 591) fügt hinzu Final Variablen, Funktionen, Methoden und Klassen. Hier sind einige Möglichkeiten, es zu verwenden:

@final Dekorateur (Klassen, Methoden)

from typing import final

@final
class Base:
    # Cannot inherit from Base

class Base:
    @final
    def foo(self):
        # Cannot override foo in subclass

Final Anmerkung

from typing import Final

PI: Final[float] = 3.14159     # Cannot set PI to another value
KM_IN_MILES: Final = 0.621371  # Type annotation is optional

class Foo:
    def __init__(self):
        self.bar: Final = "baz"   # Final instance attributes only allowed in __init__

Bitte beachten Sie, dass diese Sie wie andere Tipphinweise nicht daran hindern, die Typen zu überschreiben, aber sie helfen Linters oder IDEs, Sie vor falscher Typverwendung zu warnen.

  • Ich denke, diese Antwort ist irreführend, da man leicht den Eindruck bekommt, dass die endgültigen Qualifizierer verhindern, dass man zur Laufzeit neu zugewiesen oder überschrieben wird, was nicht der Fall ist.

    – Antonagestam

    25. November 2019 um 9:01 Uhr

  • @antonagetam es ist eine Sprachfunktion. IDEs wie Visual Studio Code und PyCharm passen sich wahrscheinlich an und zeigen automatisch eine Warnung an, wenn Sie versuchen, eine letzte Instanz neu zuzuweisen. Dies ist bereits der Fall, wenn Sie versuchen, eine Instanzvariable mit vorangestelltem Unterstrich außerhalb der Klasse zu verwenden.

    – Mama

    4. Januar 2020 um 13:55 Uhr

  • @momo Genauso wie eine Frage zu privaten Eigenschaften eine Antwort haben sollte, die erklärt, dass in Python nichts wirklich privat ist, denke ich, dass eine Antwort auf diese Frage die Verwendung von final/Final Qualifikanten sollte erklären, dass sie zur Laufzeit nichts tun. Beachten Sie, dass ich diese Frage auch beantwortet habe.

    – Antonagestam

    5. Januar 2020 um 20:38 Uhr

  • Ich stimme dem Kommentar von @antonagetam zu. @typing.final wird nur vom statischen Typprüfer verwendet. Die Antwort sollte deutlicher machen, dass dieser Decorator beim Ausführen des Skripts vollständig ignoriert wird. Dynamisch erstellte Klassen ignorieren diesen Decorator stillschweigend.

    – Conchylikultor

    20. Januar 2020 um 20:31 Uhr

Benutzer-Avatar
S. Lott

Eine Einmalzuweisungsvariable ist ein Designproblem. Sie gestalten Ihre Anwendung so, dass die Variable nur einmal gesetzt wird.

Wenn Sie Ihr Design jedoch zur Laufzeit überprüfen möchten, können Sie dies mit einem Wrapper um das Objekt tun.

class OnePingOnlyPleaseVassily(object):
    def __init__(self):
        self.value = None
    def set(self, value):
        if self.value is not None:
            raise Exception("Already set.")
        self.value = value

someStateMemo = OnePingOnlyPleaseVassily()
someStateMemo.set(aValue) # works
someStateMemo.set(aValue) # fails

Das ist umständlich, aber es erkennt Designprobleme zur Laufzeit.

Es gibt keine solche Sache. Im Allgemeinen lautet die Python-Einstellung: “Wenn Sie dies nicht ändern möchten, ändern Sie es einfach nicht”. Es ist sowieso unwahrscheinlich, dass Clients einer API einfach in Ihren undokumentierten Interna herumstochern.

Ich nehme an, Sie könnten dies umgehen, indem Sie Tupel oder benannte Tupel für die relevanten Bits Ihres Modells verwenden, die von Natur aus unveränderlich sind. Das hilft natürlich immer noch nicht bei Teilen Ihres Modells, die veränderbar sein müssen.

  • Viele andere Klassen sind ebenfalls unveränderlich: Strings, Ints, Longs, Floats.

    – S. Lott

    29. April 2009 um 14:37 Uhr

Benutzer-Avatar
Onkel Zeiv

Sie können so etwas durch die simulieren Deskriptor-Protokollda es erlaubt, das Lesen und Setzen einer Variablen nach Ihren Wünschen zu definieren.

class Foo(object):

  @property
  def myvar(self):
     # return value here

  @myvar.setter
  def myvar(self, newvalue):
     # do nothing if some condition is met

a = Foo()
print a.myvar
a.myvar = 5 # does nothing if you don't want to

  • Viele andere Klassen sind ebenfalls unveränderlich: Strings, Ints, Longs, Floats.

    – S. Lott

    29. April 2009 um 14:37 Uhr

Ab 2019 und PEP 591Python hat eine Final Typ. Es wird bis zur Veröffentlichung von Python 3.8 nicht in der Standardbibliothek verfügbar sein, aber bis dahin können Sie es über die verwenden Eingabe-Erweiterungen Bibliothek. Es wird nicht funktionieren final funktioniert jedoch in Java, da Python immer noch eine dynamisch typisierte Sprache ist. Aber wenn Sie es zusammen mit einem statischen Typprüfer wie verwenden mypy es wird Ihnen sehr ähnliche Vorteile bringen.

Da ist auch ein final Dekorateur, der angewendet werden kann, um Klassenmethoden als endgültig zu markieren und zu verhindern, dass sie überschrieben werden. Auch dies wird nur zur “Kompilierungszeit” überprüft, sodass Sie einen statischen Typprüfer in Ihren Workflow aufnehmen müssen.

1221220cookie-check“final”-Schlüsselwortäquivalent für Variablen in Python?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy