Wie deklariere ich eine Konstante in Python?
In Java machen wir:
public static final String CONST_NAME = "Name";
Wie deklariere ich eine Konstante in Python?
In Java machen wir:
public static final String CONST_NAME = "Name";
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
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:
constant
, die einen Ausdruck annimmt und diesen verwendet, um einen "Getter" zu konstruieren - eine Funktion, die ausschließlich den Wert des Ausdrucks zurückgibt.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
property
-Funktion, um ein Objekt zu konstruieren, das "gesetzt" oder "gelesen" werden kann.property
-Funktion mit fset
und fget
benannt sind.property
-Funktion zu übergeben.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
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.
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.