Реализация enum похожа на namedtuple
с использованием namedtuple
. Эта enum
функция создает класс с namedtuple
и создает экземпляр класса с предоставленными аргументами. Аргументы - это строки tuple
или list
. Форма аргументов tuple
или list
используется для предоставления значения константам, таким образом сбрасывая последовательность значений. По умолчанию константы оцениваются, начиная с нуля.
def enum(name, *args):
from collections import namedtuple
kwargs = {}
start = 0
for arg in args:
if isinstance(arg, basestring):
kwargs[arg] = start
start += 1
elif isinstance(arg, (tuple, list)):
if len(arg) != 2:
raise ValueError('"{}" must be a two element tuple or list'.format(arg))
attr, start = arg
if isinstance(attr, basestring):
if isinstance(start, int):
kwargs[attr] = start
start += 1
else:
raise TypeError('second element of "{}" must be of type "int"'.format(arg))
else:
raise TypeError('first element of "{}" must be sub type of "basestring"'.format(arg))
else:
raise TypeError('Argument "{}" must be either sub type of "basestring", "tuple" or "list" of ("basestring", "int")'.format(arg))
if isinstance(name, basestring):
return namedtuple(name, kwargs.keys())(**kwargs)
raise TypeError('Argument "{}" must be an instance of "basestring"'.format(name))
Usage;
In [663]: Color = enum('Color', 'black', 'white', 'red')
In [664]: Color.black
Out[664]: 0
In [665]: Color.red
Out[665]: 2
In [666]: #To start from 1
In [667]: Color = enum('Color', ('black',1), 'white', 'red')
In [668]: Color.black
Out[668]: 1
In [669]: Color.red
Out[669]: 3
In [670]: Animal = enum('Animal','cat', 'dog', ['lion',10],'tiger')
In [671]: Animal.dog
Out[671]: 1
In [672]: Animal.tiger
Out[672]: 11
In [673]: Animal.tiger = 12
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-673-8823b3c2482c> in <module>()
----> 1 Animal.tiger = 12
AttributeError: can't set attribute