1275 Stimmen

Wie erstelle ich eine Konstante in Python?

Wie deklariere ich eine Konstante in Python?

In Java machen wir:

public static final String CONST_NAME = "Name";

1236voto

Felix Kling Punkte 751464

Sie können in Python keine Variable oder Wert als Konstante deklarieren.


Um Programmierern anzuzeigen, dass eine Variable eine Konstante ist, schreibt man sie in der Regel in Großbuchstaben:

CONST_NAME = "Name"

Um Ausnahmen zu erheben, wenn Konstanten geändert werden, siehe Konstanten in Python von Alex Martelli. Beachten Sie, dass dies in der Praxis nicht üblich ist.


Ab Python 3.8 gibt es eine typing.Final Variablenannotation, die statischen Typüberprüfern (wie mypy) mitteilt, dass Ihre Variable nicht neu zugewiesen werden sollte. Dies entspricht am ehesten Javas final. Es verhindert jedoch nicht tatsächlich die Neuweisenung:

from typing import Final

a: Final[int] = 1

# Funktioniert einwandfrei, aber mypy meldet einen Fehler, wenn Sie mypy darauf ausführen:
a = 2

420voto

inv Punkte 4591

Es gibt kein const Schlüsselwort wie in anderen Sprachen, jedoch ist es möglich, eine Eigenschaft zu erstellen, die eine "Getter-Funktion" zum Lesen der Daten hat, aber keine "Setter-Funktion" zum Überschreiben der Daten. Dies schützt die Bezeichnung effektiv davor, geändert zu werden.

Hier ist eine alternative Implementierung unter Verwendung einer Klassen-Eigenschaft:

Beachten Sie, dass der Code für einen Leser, der sich über Konstanten wundert, weit entfernt von einfach ist. Siehe Erklärung unten.

def constant(f):
    def fset(self, value):
        raise TypeError
    def fget(self):
        return f()
    return property(fget, fset)

class _Const(object):
    @constant
    def FOO():
        return 0xBAADFACE
    @constant
    def BAR():
        return 0xDEADBEEF

CONST = _Const()

print(hex(CONST.FOO))  # -> '0xbaadfaceL'

CONST.FOO = 0
##Traceback (most recent call last):
##  File "example1.py", line 22, in 
##    CONST.FOO = 0
##  File "example1.py", line 5, in fset
##    raise TypeError
##TypeError

Code-Erklärung:

  1. Definieren Sie eine Funktion constant, die einen Ausdruck annimmt und diesen verwendet, um einen "Getter" zu konstruieren - eine Funktion, die ausschließlich den Wert des Ausdrucks zurückgibt.
  2. Die Setter-Funktion wirft einen TypeError, so dass sie schreibgeschützt ist.
  3. Verwenden Sie die zuvor erstellte constant-Funktion als Dekoration, um schnell schreibgeschützte Eigenschaften zu definieren.

Und auf eine etwas altmodischere Weise:

(Der Code ist ziemlich knifflig, weitere Erklärungen unten)

class _Const(object):
    def FOO():
        def fset(self, value):
            raise TypeError
        def fget(self):
            return 0xBAADFACE
        return property(**locals())
    FOO = FOO()  # Eigenschaft definieren.

CONST = _Const()

print(hex(CONST.FOO))  # -> '0xbaadfaceL'

CONST.FOO = 0
##Traceback (most recent call last):
##  File "example2.py", line 16, in 
##    CONST.FOO = 0
##  File "example2.py", line 6, in fset
##    raise TypeError
##TypeError
  1. Um die Bezeichnung FOO zu definieren, definieren Sie zuerst zwei Funktionen (fset, fget - die Namen sind meine Wahl).
  2. Verwenden Sie dann die integrierte property-Funktion, um ein Objekt zu konstruieren, das "gesetzt" oder "gelesen" werden kann.
  3. Beachten Sie, dass die ersten beiden Parameter der property-Funktion mit fset und fget benannt sind.
  4. Nutzen Sie die Tatsache, dass wir genau diese Namen für unsere eigenen Getter & Setter gewählt haben, und erstellen Sie ein Schlüsselwort-Wörterbuch, indem Sie die ** (doppelten Sterne) auf alle lokalen Definitionen dieses Bereichs anwenden, um Parameter an die property-Funktion zu übergeben.

149voto

Anurag Uniyal Punkte 81337

Statt dass in Python die Sprache etwas durchsetzt, verwenden die Leute Namenskonventionen z.B. __method für private Methoden und verwenden _method für geschützte Methoden.

Also kannst du auf dieselbe Weise die Konstante einfach als Großbuchstaben deklarieren, z.B.:

MY_CONSTANT = "one"

Wenn du möchtest, dass diese Konstante niemals geändert wird, kannst du auf Attributzugriff zugreifen und Tricks anwenden, aber ein einfacher Ansatz ist es, eine Funktion zu deklarieren:

def MY_CONSTANT():
    return "one"

Das einzige Problem ist, dass du überall MY_CONSTANT() machen musst, aber wieder ist MY_CONSTANT = "one" in Python (normalerweise) der richtige Weg.


Du kannst auch namedtuple() verwenden, um Konstanten zu erstellen:

>>> from collections import namedtuple
>>> Constants = namedtuple('Constants', ['pi', 'e'])
>>> constants = Constants(3.14, 2.718)
>>> constants.pi
3.14
>>> constants.pi = 3
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: can't set attribute

101voto

Jon Betts Punkte 2713

Ich habe kürzlich ein sehr prägnantes Update gefunden, das automatisch aussagekräftige Fehlermeldungen erzeugt und den Zugriff über __dict__ verhindert:

class CONST(object):
    __slots__ = ()
    FOO = 1234

CONST = CONST()

# ----------
print(CONST.FOO)    # 1234

CONST.FOO = 4321              # AttributeError: Attribut 'FOO' des 'CONST'-Objekts ist schreibgeschützt
CONST.__dict__['FOO'] = 4321  # AttributeError: 'CONST'-Objekt hat kein Attribut '__dict__'
CONST.BAR = 5678              # AttributeError: 'CONST'-Objekt hat kein Attribut 'BAR'

Wir definieren uns über uns selbst, um uns zu einer Instanz zu machen, und verwenden dann Slots, um sicherzustellen, dass keine zusätzlichen Attribute hinzugefügt werden können. Dadurch wird auch der Zugriff über __dict__ entfernt. Natürlich kann das gesamte Objekt immer noch neu definiert werden.

Bearbeitung - Ursprüngliche Lösung

Vielleicht übersehe ich hier einen Trick, aber das scheint für mich zu funktionieren:

class CONST(object):
    FOO = 1234

    def __setattr__(self, *_):
        pass

CONST = CONST()

# ----------

print CONST.FOO    # 1234

CONST.FOO = 4321
CONST.BAR = 5678

print CONST.FOO    # Immer noch 1234!
print CONST.BAR    # Fehler AttributeError

Das Erstellen der Instanz ermöglicht es der magischen Methode __setattr__, Versuche abzufangen, die die Variable FOO setzen sollen. Hier könnten Sie eine Ausnahme werfen, wenn Sie möchten. Die Instanziierung der Instanz über den Klassennamen verhindert den direkten Zugriff über die Klasse.

Es ist eine echte Mühe für einen Wert, aber Sie könnten viele Dinge an Ihr CONST-Objekt anhängen. Das Anbringen eines Oberklassennamens scheint auch ein wenig unordentlich zu sein, aber insgesamt denke ich, dass es recht prägnant ist.

50voto

Saeed Baig Punkte 999

Python hat keine Konstanten.

Vielleicht ist die einfachste Alternative, eine Funktion dafür zu definieren:

def MY_CONSTANT():
    return 42

MY_CONSTANT() hat jetzt alle Funktionalitäten einer Konstanten (plus ein paar lästige Klammern).

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