2015-04-22 22 views
6

Questa è principalmente una domanda in "stile Python".Costanti di raggruppamento in python

Ho un modulo che utilizza un numero di costanti che dovrebbe essere raggruppato.

Diciamo che abbiamo cani e gatti e ognuno di loro ha il numero di zampe e il cibo preferito.

Nota che

  1. vogliamo modellare nulla, ma queste costanti su cani e gatti
  2. molto probabilmente avremo più animali in futuro.
  3. queste costanti non verranno utilizzate al di fuori del modulo corrente.

ho pensato le seguenti soluzioni:


costanti a livello di modulo

DOG_NUMBER_OF_LEGS = 4 
DOG_FAVOURITE_FOOD = ["Socks", "Meat"] 
CAT_NUMBER_OF_LEGS = 4 
CAT_FAVOURITE_FOOD = ["Lasagna", "Fish"] 

Sembrano non proprio raggruppati, ma penso che sia la soluzione che preferisco.


Classi come spazi dei nomi

class Dog(object): 
    NUMBER_OF_LEGS = 4 
    DOG_FAVOURITE_FOOD = ["Socks", "Meat"] 
class Cat(object): 
    NUMBER_OF_LEGS = 4 
    FAVOURITE_FOOD = ["Lasagna", "Fish"] 

Non mi piace questa soluzione come avremo classe che non rimarremo uso e possono essere in realtà un'istanza.


Dizionario di costanti

ANIMALS_CONFIG = { 
    "DOG" : { 
    "NUMBER_OF_LEGS" : 4, 
    "FAVOURITE_FOOD" : ["Socks", "Meat"] 
    }, 
    "CAT" : { 
    "NUMBER_OF_LEGS" : 4, 
    "FAVOURITE_FOOD" : ["Lasagna", "Fish"] 
    } 
} 

Ho anche pensato di aggiungere moduli, ma io non ci tengo a esporre queste costanti interne


qual è il modo più divinatorio per fallo/come lo faresti?

+2

Si potrebbe anche avere una classe '' Animal' con dog' e 'cat' istanze di quella classe. – syntonym

+4

Oppure puoi anche usare [tuple con nome] (https://docs.python.org/2.7/library/collections.html#collections.namedtuple). – syntonym

+0

Come li userete nel vostro codice? Vuoi iterare o selezionare? Da dove proviene il parametro di selezione? –

risposta

6

vorrei andare per una quarta opzione, preferendo una collections.namedtuple:

Animal = namedtuple('Animal', 'number_of_legs favourite_food') 

È quindi creare casi come:

DOG = Animal(4, ['Socks', 'Meat']) 
CAT = Animal(4, ['Lasagna', 'Fish']) 

e accedere ai valori esternamente come:

from animals import CAT 

print CAT.number_of_legs 

Non ha davvero senso avere lezioni se non hai bisogno di creare alcun metodo, e penso che per m di accesso di cui sopra è più ordinato rispetto ad es .:

from animals import animals 

print animals['CAT']['number_of_legs'] 

namedtuple s, come la vaniglia tuple s, sono immutabili , anche, quindi non si può accidentalmente riassegnare ad esempio CAT.number_of_legs = 2 da qualche parte.

Infine, il namedtuple è una struttura di dati leggero, che può essere importante se si sta creando un sacco di animali:

>>> import sys 
>>> sys.getsizeof({'number_of_legs': 4, 'favourite_food': ['Lasagna', 'Fish']}) 
140 
>>> from collections import namedtuple 
>>> Animal = namedtuple('Animal', 'number_of_legs favourite_food') 
>>> sys.getsizeof(Animal(4, ['Lasagna', 'Fish'])) 
36 
1

Preferisco l'approccio del dizionario, poiché è più leggibile e meglio organizzato, ma credo che sia una questione di preferenze personali.

Anche l'utilizzo delle classi non sembra una cattiva idea se si utilizza una classe con solo variabili statiche e metodi come this e non si istanziano mai.

4

Non esiste una risposta valida per tutti, dipende in realtà da quante costanti si devono gestire, come le si usa, se la spedizione del polimorfismo ha senso o meno e la fase della luna.

Ora nel tuo esempio, poiché hai due o più serie di costanti con una struttura e un significato simili, sceglierei la soluzione "Classi come spazi dei nomi".

FWIW evitare una classe di essere istanziare non è poi così difficile:

>>> class Foo(object): 
... def __new__(cls): 
...  return cls 
... 
>>> Foo() 
<class '__main__.Foo'> 

Ma documentazione dovrebbe essere sufficiente - ricordate che il vostro "costanti" sono solo costanti per convenzione in ogni caso.