Domanda

    

Questa domanda ha già una risposta qui:

         

Ho usato una piccola classe per emulare Enum in alcuni progetti Python. C'è un modo migliore o ha più senso in alcune situazioni?

Codice classe qui:

class Enum(object):
'''Simple Enum Class
Example Usage:
>>> codes = Enum('FOO BAR BAZ') # codes.BAZ will be 2 and so on ...'''
def __init__(self, names):
    for number, name in enumerate(names.split()):
        setattr(self, name, number)
È stato utile?

Soluzione

Ci sono molte buone discussioni qui .

Altri suggerimenti

Gli enum sono stati proposti per l'inclusione nella lingua prima, ma sono stati respinti (vedi http://www.python.org/dev/peps/pep-0354/ ), sebbene ci siano pacchetti esistenti che potresti usare invece di scrivere la tua implementazione:

Il caso enum più comune sono i valori enumerati che fanno parte di un modello di progettazione di stato o strategia. Gli enum sono stati specifici o specifiche strategie opzionali da utilizzare. In questo caso, fanno quasi sempre parte di una definizione di classe

class DoTheNeedful( object ):
    ONE_CHOICE = 1
    ANOTHER_CHOICE = 2 
    YET_ANOTHER = 99
    def __init__( self, aSelection ):
        assert aSelection in ( self.ONE_CHOICE, self.ANOTHER_CHOICE, self.YET_ANOTHER )
        self.selection= aSelection

Quindi, in un client di questa classe.

dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )

Quello che vedo più spesso è questo, nel contesto del modulo di livello superiore:

FOO_BAR = 'FOO_BAR'
FOO_BAZ = 'FOO_BAZ'
FOO_QUX = 'FOO_QUX'

... e successive ...

if something is FOO_BAR: pass # do something here
elif something is FOO_BAZ: pass # do something else
elif something is FOO_QUX: pass # do something else
else: raise Exception('Invalid value for something')

Nota che l'uso di è piuttosto che == sta correndo un rischio qui - presume che la gente stia usando your_module.FOO_BAR piuttosto che la stringa 'FOO_BAR' (che normalmente sarà internata in modo tale che sia corrisponderà, ma di certo non si può contare) e quindi potrebbe non essere appropriato a seconda del contesto.

Un vantaggio nel farlo in questo modo è che osservando ovunque sia memorizzato un riferimento a quella stringa, è immediatamente ovvio da dove proviene; FOO_BAZ è molto meno ambiguo di 2 .

Oltre a ciò, l'altra cosa che offende la mia sensibilità Pythonic per quanto riguarda la classe che proponi è l'uso di split () . Perché non passare semplicemente in una tupla, in un elenco o in altri enumerabili per cominciare?

Il modo integrato per fare enum è:

(FOO, BAR, BAZ) = range(3)

che funziona bene per piccoli set, ma presenta alcuni svantaggi:

  • devi contare il numero di elementi a mano
  • non puoi saltare valori
  • se aggiungi un nome, devi anche aggiornare il numero dell'intervallo

Per un'implementazione enum completa in python, vedere: http://code.activestate.com/recipes/67107/

Ho iniziato con qualcosa che assomiglia molto alla risposta di S.Lott ma ho solo sovraccaricato 'str' ed 'eq' (invece dell'intera classe di oggetti) in modo da poter stampare e confrontare il valore dell'enum.

class enumSeason():
    Spring = 0
    Summer = 1
    Fall = 2
    Winter = 3
    def __init__(self, Type):
        self.value = Type
    def __str__(self):
        if self.value == enumSeason.Spring:
            return 'Spring'
        if self.value == enumSeason.Summer:
            return 'Summer'
        if self.value == enumSeason.Fall:
            return 'Fall'
        if self.value == enumSeason.Winter:
            return 'Winter'
    def __eq__(self,y):
        return self.value==y.value

Stampa (x) produrrà il nome anziché il valore e due valori che contengono Primavera saranno uguali tra loro.

   >>> x = enumSeason(enumSeason.Spring)
   >>> print(x)
   Spring
   >>> y = enumSeason(enumSeason.Spring)
   >>> x == y
   True
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top