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";

7voto

MVP Punkte 941

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

6voto

K4liber Punkte 632

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'

6voto

Xavier Ho Punkte 15307

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.

6voto

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.

5voto

kephircheek Punkte 71

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.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