Есть ли лучший способ получить именованный ряд констант (перечисление) в Python? [Дубликат]

17

Просто посмотрим на способы получения именных констант в python.

class constant_list:
    (A_CONSTANT, B_CONSTANT, C_CONSTANT) = range(3)

Тогда, конечно, вы можете ссылаться на него так:

constant_list.A_CONSTANT

Я полагаю, вы могли бы использовать словарь, используя строки:

constant_dic = {
    "A_CONSTANT" : 1,
    "B_CONSTANT" : 2,
    "C_CONSTANT" : 3,}

и ссылайтесь на него следующим образом:

constant_dic["A_CONSTANT"]

Поэтому мой вопрос прост. Есть ли лучшие способы сделать это? Не сказать, что они неадекватны или что-то еще, просто любопытно - любые другие распространенные идиомы, которые я пропустил?

Спасибо заранее.

    
задан Bernard 13.10.2008 в 08:43
источник
  • Это дубликат (по крайней мере) этого вопроса и этого вопроса. Я действительно хочу, чтобы поиск SO занял лучшую работу. –  dF. 13.10.2008 в 15:11

6 ответов

19

В течение 2,3 или после:

class Enumerate(object):
  def __init__(self, names):
    for number, name in enumerate(names.split()):
      setattr(self, name, number)

Для использования:

 codes = Enumerate('FOO BAR BAZ')

codes.BAZ будет равно 2 и так далее.

Если у вас есть только 2.2, перед этим:

 from __future__ import generators

 def enumerate(iterable):
   number = 0
   for name in iterable:
     yield number, name
     number += 1

( Это было взято из здесь )     

ответ дан Tomalak 13.10.2008 в 08:48
источник
  • Наследование с объекта кажется ненужным. Но это работает, и кажется довольно элегантным. –  Bernard 13.10.2008 в 08:59
  • вы наследуете объект, чтобы создать класс нового стиля. –  hop 13.10.2008 в 14:01
  • Если вы хотите предоставить ключи перечисления, которые являются действительными строками и ассоциируют с ним значение Animal = Enum ('Animal', {'ant1.0': 1, 'bee': 2}) –  Alex Punnen 29.03.2016 в 08:38
2

Я считаю, что рецепт класса перечисления (Active State, Python Cookbook ) очень эффективен.

Плюс у него есть функция поиска, которая хороша.

PEV     

ответ дан Simon Peverett 13.10.2008 в 08:48
источник
2

Альтернативная конструкция для константы:

constants = ["A_CONSTANT", "B_CONSTANT", "C_CONSTANT"]
constant_dic = dict([(c,i) for i, c in enumerate(constants)])
    
ответ дан Anthony Cramp 13.10.2008 в 08:55
источник
2

Следующие действия, такие как classisc «написано на камне» C enum - как только это определено, вы не можете его изменить, вы можете читать только его значения. Вы также не можете создать экземпляр. Все, что вам нужно сделать, это «import enum.py» и получить из класса Enum.

# this is enum.py
class EnumException( Exception ):
   pass

class Enum( object ):
   class __metaclass__( type ):
      def __setattr__( cls, name, value ):
         raise EnumException("Can't set Enum class attribute!")
      def __delattr__( cls, name ):
         raise EnumException("Can't delete Enum class attribute!")

   def __init__( self ):
      raise EnumException("Enum cannot be instantiated!")

Это тестовый код:

# this is testenum.py
from enum import *

class ExampleEnum( Enum ):
   A=1
   B=22
   C=333

if __name__ == '__main__' :

   print "ExampleEnum.A |%s|" % ExampleEnum.A
   print "ExampleEnum.B |%s|" % ExampleEnum.B
   print "ExampleEnum.C |%s|" % ExampleEnum.C
   z = ExampleEnum.A
   if z == ExampleEnum.A:
      print "z is A"

   try:
       ExampleEnum.A = 4   
       print "ExampleEnum.A |%s| FAIL!" % ExampleEnum.A
   except EnumException:
       print "Can't change Enum.A (pass...)"

   try:
       del ExampleEnum.A
   except EnumException:
       print "Can't delete Enum.A (pass...)"

   try:
       bad = ExampleEnum()
   except EnumException:
       print "Can't instantiate Enum (pass...)"
    
ответ дан Kevin Little 13.10.2008 в 18:02
источник
2

Это лучшее, что я видел: «Первичный класс в Python»

Ссылка

Он дает вам класс, и класс содержит все перечисления. Перечисления можно сравнивать друг с другом, но не имеют какой-либо особой ценности; вы не можете использовать их как целочисленное значение. (Сначала я сопротивлялся, потому что я привык к C перечислениям, которые являются целыми значениями. Но если вы не можете использовать его как целое число, вы не можете использовать его как целое число по ошибке , поэтому В целом я думаю, что это победа.) Каждое перечисление является уникальным объектом. Вы можете печатать перечисления, вы можете перебирать их, вы можете проверить, что значение перечисления «включено» в перечисление. Это довольно полный и гладкий.

    
ответ дан steveha 18.11.2009 в 03:17
источник
1

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

class Enumeration(object):
    def __init__(self, possibilities):
        self.possibilities = set(possibilities.split())

    def all(self):
        return sorted(self.possibilities)

    def __getattr__(self, name):
        if name in self.possibilities:
            return name
        raise AttributeError("Invalid constant: %s" % name)

Затем вы можете использовать его следующим образом:

>>> enum = Enumeration("FOO BAR")
>>> print enum.all()
['BAR', 'FOO']
>>> print enum.FOO
FOO
>>> print enum.FOOBAR
Traceback (most recent call last):
  File "enum.py", line 17, in <module>
    print enum.FOOBAR
  File "enum.py", line 11, in __getattr__
    raise AttributeError("Invalid constant: %s" % name)
AttributeError: Invalid constant: FOOBAR
    
ответ дан DzinX 13.10.2008 в 09:17
источник
  • Очень приятно. Но на самом деле это не перечисление? :п –  Bernard 13.10.2008 в 09:28
  • Хм ... правильно :-) Но зачем вам нужно eNUMERATION в Python, так или иначе? –  DzinX 13.10.2008 в 09:40
  • Ну, цифры тоже неизменяемы. Они просто не задокументированы. –  John Fouhy 14.10.2008 в 01:57