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";
Wir können ein Deskriptorobjekt erstellen.
class Konstante:
def __init__(self, value=None):
self.value = value
def __get__(self, instanz, eigentuemer):
return self.value
def __set__(self, instanz, value):
raise ValueError("Du kannst eine Konstante nicht ändern")
1) Wenn wir mit Konstanten auf der Instanzebene arbeiten möchten, dann:
class A:
NULL = Konstante()
NUM = Konstante(0xFF)
class B:
NAME = Konstante('bar')
LISTA = Konstante([0,1,'UNENDLICH'])
>>> obj=A()
>>> print(obj.NUM) #=> 255
>>> obj.NUM =100
Traceback (most recent call last):
File "", line 1, in
ValueError: Du kannst eine Konstante nicht ändern
2) Wenn wir Konstanten nur auf Klassenebene erstellen möchten, könnten wir eine Metaklasse verwenden, die als Container für unsere Konstanten (unsere Deskriptorobjekte) dient; alle absteigenden Klassen erben unsere Konstanten (unsere Deskriptorobjekte) ohne das Risiko, dass sie geändert werden können.
# Metaklasse meiner Klasse Foo
class FooMeta(type): pass
# Klasse Foo
class Foo(metaclass=FooMeta): pass
# Ich erstelle Konstanten in meiner Metaklasse
FooMeta.NUM = Konstante(0xff)
FooMeta.NAME = Konstante('FOO')
>>> Foo.NUM #=> 255
>>> Foo.NAME #=> 'FOO'
>>> Foo.NUM = 0 #=> ValueError: Du kannst eine Konstante nicht ändern
Wenn ich eine Unterklasse von Foo erstelle, wird diese Klasse die Konstante erben, ohne die Möglichkeit, sie zu ändern
class Bar(Foo): pass
>>> Bar.NUM #=> 255
>>> Bar.NUM = 0 #=> ValueError: Du kannst eine Konstante nicht ändern
Ich deklariere konstante Werte mit einer gefrorenen Datenklasse wie folgt:
from dataclasses import dataclass
@dataclass(frozen=True)
class _Const:
SOME_STRING = 'some_string'
SOME_INT = 5
Const = _Const()
# In einer anderen Datei importiere Const und versuche es
print(Const.SOME_STRING) # ES IST OK!
Const.SOME_INT = 6 # dataclasses.FrozenInstanceError: cannot assign to field 'SOME_INT'
Der Pythonische Weg, "Konstanten" zu deklarieren, besteht im Grunde aus einer Variablen auf Modulebene:
ROT = 1
GRÜN = 2
BLAU = 3
Und dann schreiben Sie Ihre Klassen oder Funktionen. Da Konstanten fast immer Ganzzahlen sind und in Python auch unveränderlich sind, haben Sie eine sehr geringe Chance, sie zu ändern.
Es sei denn, Sie setzen explizit ROT = 2
.
Es gibt einen saubereren Weg, dies mit namedtuple zu tun:
from collections import namedtuple
def make_consts(name, **kwargs):
return namedtuple(name, kwargs.keys())(**kwargs)
Beispiel Verwendung
CONSTS = make_consts("baz1",
foo=1,
bar=2)
Mit diesem genauen Ansatz können Sie Ihre Konstanten in Namespaces unterteilen.
Ich versuche verschiedene Möglichkeiten zu finden, um eine echte Konstante in Python zu erstellen und vielleicht habe ich die hübsche Lösung gefunden.
Beispiel:
Container für Konstanten erstellen
>>> DAYS = Constants(
... MON=0,
... TUE=1,
... WED=2,
... THU=3,
... FRI=4,
... SAT=5,
... SUN=6
... )
Wert aus dem Container abrufen
>>> DAYS.MON
0
>>> DAYS['MON']
0
Mit reinen Python-Datenstrukturen darstellen
>>> list(DAYS)
['WED', 'SUN', 'FRI', 'THU', 'MON', 'TUE', 'SAT']
>>> dict(DAYS)
{'WED': 2, 'SUN': 6, 'FRI': 4, 'THU': 3, 'MON': 0, 'TUE': 1, 'SAT': 5}
Alle Konstanten sind unveränderlich
>>> DAYS.MON = 7
...
AttributeError: Unveränderliches Attribut
>>> del DAYS.MON
...
AttributeError: Unveränderliches Attribut
Autocomplete nur für Konstanten
>>> dir(DAYS)
['FRI', 'MON', 'SAT', 'SUN', 'THU', 'TUE', 'WED']
Sortierung wie list.sort
>>> DAYS.sort(key=lambda (k, v): v, reverse=True)
>>> list(DAYS)
['SUN', 'SAT', 'FRI', 'THU', 'WED', 'TUE', 'MON']
Kompatibilität mit python2
und python3
Einfacher Container für Konstanten
from collections import OrderedDict
from copy import deepcopy
class Constants(object):
"""Container of constant"""
__slots__ = ('__dict__')
def __init__(self, **kwargs):
if list(filter(lambda x: not x.isupper(), kwargs)):
raise AttributeError('Konstantenname sollte großgeschrieben sein.')
super(Constants, self).__setattr__(
'__dict__',
OrderedDict(map(lambda x: (x[0], deepcopy(x[1])), kwargs.items()))
)
def sort(self, key=None, reverse=False):
super(Constants, self).__setattr__(
'__dict__',
OrderedDict(sorted(self.__dict__.items(), key=key, reverse=reverse))
)
def __getitem__(self, name):
return self.__dict__[name]
def __len__(self):
return len(self.__dict__)
def __iter__(self):
for name in self.__dict__:
yield name
def keys(self):
return list(self)
def __str__(self):
return str(list(self))
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, str(self.__dict__))
def __dir__(self):
return list(self)
def __setattr__(self, name, value):
raise AttributeError("Unveränderliches Attribut")
def __delattr__(*_):
raise AttributeError("Unveränderliches Attribut")
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.