2015-04-22 4 views
6

Это, в основном, вопрос «хорошего стиля питона».Константы группировки в python

У меня есть модуль, который использует несколько констант, которые, по его мнению, должны быть сгруппированы.

Допустим, у нас есть Собаки и кошка, и у каждого из них есть количество ног и любимая еда.

Обратите внимание, что

  1. мы хотим, чтобы моделировать ничего, кроме этих констант о собаках и кошках
  2. вполне вероятно, мы будем иметь больше животных в будущем.
  3. Эти константы не будут использоваться за пределами текущего модуля.

Я думал о следующих решениях:


Константы на уровне модуля

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

Они, кажется, на самом деле не сгруппированы, но я думаю, что это решение, которое я предпочитаю.


Классы в пространствах имен

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

Мне не нравится это решение, как мы будем иметь класс, который мы не будем использовать, и они могут быть на самом деле инстанцированный.


словарь констант

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

Я также думал о добавлении подмодулей, но я действительно не хочу, чтобы выставить эти внутренние константы


что является наиболее вещим способом сделайте это/как бы вы это сделали?

+2

Вы также можете иметь класс 'Animal' с' 'dog' и cat' экземпляры этого класса. – syntonym

+4

Или вы также можете использовать [named tuples] (https://docs.python.org/2.7/library/collections.html#collections.namedtuple). – syntonym

+0

Как вы будете использовать их в своем коде? Вы будете повторять или выбирать? Откуда будет параметр выбора? –

ответ

6

Я хотел бы пойти на четвертый вариант, предпочитая collections.namedtuple:

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

Вы затем создать экземпляры, такие как:

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

и получить доступ к значениям наружно:

from animals import CAT 

print CAT.number_of_legs 

Нет смысла иметь классы, если вам не нужно создавать какие-либо методы, и я думаю, что для м доступа выше, чем аккуратнее например .:

from animals import animals 

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

namedtuple s, как ваниль tuple с, являются неизменны, тоже, так что вы не можете случайно переназначить, например, CAT.number_of_legs = 2 где-то.

Наконец, namedtuple представляет собой облегченный структура данных, которая может быть важно, если вы создаете много животных:

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

Я хотел бы использовать словарь, поскольку он выглядит более читаемым и лучше организованным, но я считаю, что это вопрос личных предпочтений.

Использование классов также не похоже на плохую идею, если вы используете класс только с статическими переменными и методами, такими как this, и вы никогда не создаете их.

4

Нет ответа на один размер, это действительно зависит от того, сколько констант вы должны обрабатывать, как вы их используете, если отправка полиморфизма имеет смысл или нет, и фаза луны.

Теперь в вашем примере, поскольку у вас есть два или более набора констант со сходной структурой и значением, я бы выбрал решение «классы как пространства имен».

FWIW предотвращение класса от того инстанциировано не так уж трудно:

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

Но документация должна быть достаточно - помните, что ваша «константа» только постоянные по соглашению в любом случае.