Ist es möglich, eine Klasse zu definieren Konstante innerhalb einer Enum?
Python 3.4 bringt ein neues Modul enum
, die fügt eine der Aufzählungstyp um die Sprache. Die Dokumentation für enum.Enum
bietet ein Beispiel zu zeigen, wie es kann erweitert werden:
>>> class Planet(Enum):
... MERCURY = (3.303e+23, 2.4397e6)
... VENUS = (4.869e+24, 6.0518e6)
... EARTH = (5.976e+24, 6.37814e6)
... MARS = (6.421e+23, 3.3972e6)
... JUPITER = (1.9e+27, 7.1492e7)
... SATURN = (5.688e+26, 6.0268e7)
... URANUS = (8.686e+25, 2.5559e7)
... NEPTUNE = (1.024e+26, 2.4746e7)
... def __init__(self, mass, radius):
... self.mass = mass # in kilograms
... self.radius = radius # in meters
... @property
... def surface_gravity(self):
... # universal gravitational constant (m3 kg-1 s-2)
... G = 6.67300E-11
... return G * self.mass / (self.radius * self.radius)
...
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
Diesem Beispiel wird außerdem veranschaulicht ein problem mit Enum
: in der surface_gravity()
Eigenschaft Methode, eine Konstante G
definiert, die normalerweise definiert werden, die auf Klassen-Ebene - aber Versuch zu tun, so innerhalb von ein Enum
würde einfach hinzufügen, dass es als eines der Mitglieder der enum, so dass anstelle es definiert wurden, die innerhalb der Methode.
Wenn die Klasse wollte diese Konstante verwenden, die in anderen Methoden, es müsste definiert werden, die es als gut, was natürlich nicht ideal ist.
Gibt es eine Möglichkeit, eine Klasse zu definieren Konstanten, die innerhalb einer Enum
oder einige Abhilfe, um den gleichen Effekt erzielen?
- Was ist das problem mit einem Modul-Ebene konstant?
- manchmal eine Konstante ist spezifisch für eine Klasse.
- Ich weiß, das Beispiel ist aus dem offiziellen Google docs, aber ist es wirklich eine gute Idee? Dies könnte ein
has-a
Beziehung stattis-a
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist die erweiterte Verhalten, die nicht benötigt werden in 90+% der Aufzählungen erstellt.
Laut der docs:
Wenn Sie So wollen, eine klassenkonstante haben Sie mehrere Möglichkeiten:
__init__
descriptor
Erstellen die Konstante in
__init__
und hinzufügen nachdem die Klasse erstellt wurde, die beide darunter leiden, dass nicht alle die Klasse info an einem Ort versammelt.Mixins in Verbindung kann sicherlich verwendet werden, wenn entsprechende (sehen dnozay Antwort für ein gutes Beispiel), aber in diesem Fall kann auch vereinfacht werden, indem mit einer base
Enum
Klasse mit den tatsächlichen Konstanten eingebaut.Erste, die Konstante, die verwendet werden in den folgenden Beispielen:
Und die single-use-Enum-Beispiel:
Und, schließlich, die multi-use-Enum-Beispiel:
Hinweis:
Den
Constant
G
wirklich nicht. Man könnte rebindG
um etwas anderes:Wenn Sie es wirklich brauchen, um konstant sein (aka nicht rebindable), dann verwenden Sie die neue aenum Bibliothek [1], die blockieren, weisen Sie
constant
s sowieEnum
Mitglieder.1 Offenlegung: ich bin der Autor des Python stdlib
Enum
, dieenum34
backport, und die Erweiterte Aufzählung (aenum
) Bibliothek.Constant
Klasse über dieclassconstant()
Funktion zurückgeben ein Verschluss @AnttiHaapala vorgeschlagen? Ich merke, dassPlanet.__dict__['G']
hat eine etwas schönererepr
in Ihrer version; gibt es sonst noch etwas?__repr__
, hinzufügen. Ich hatte es gerade getan.Die eleganteste Lösung (IMHO) ist die Verwendung von Mixins in Verbindung /base-Klasse zu bieten das richtige Verhalten.
Satellite
undPlanet
.Satellite
undPlanet
eventuell ein anderes Verhalten)Hier ist ein Beispiel, wo definieren Sie zunächst Ihr Verhalten:
Dann erstellen Sie Ihre
Enum
mit der richtigen base-classes /Mixins in Verbindung.G = Constant(6.67300E-11)
sollteG = 6.67300E-11
.Der Grund, warum @ - Eigenschaft funktioniert NICHT und classconstant funktioniert ist ganz einfach, und erklärt, in der Antwort hier
Damit, den code in
classproperty
ist eigentlich eine Verallgemeinerung vonproperty
sind, fehlt dieif instance is None
Teil.Einen
Eigenschaft
kann verwendet werden, um die meisten, die das Verhalten einer Klasse Konstante:Das wäre ein wenig aufwendig, wenn Sie wollten, um zu definieren, eine große Anzahl von Konstanten, so könnte man definieren, eine helper-Funktion außerhalb der Klasse:
... und verwenden Sie es wie folgt:
Einer Einschränkung dieses Ansatzes ist, dass es funktioniert nur für Instanzen der Klasse und nicht die Klasse selbst:
TLDR; NEIN, es kann nicht getan werden, innerhalb einer Enum-Klasse.
Sagte dieser, wie die anderen Antworten zeigten, es gibt Möglichkeiten zu bekommen, wie Klasse Eigentum verbundenen Werte einer Enum (D. H. über Vererbung /Mixins in Verbindung), aber solche Werte sind nicht "definiert .. innerhalb einer Enum".