Подтвердить что ты не робот

Python Многослойные искусственные перечисления с использованием диапазона

Я пытаюсь создать класс типа enum в Python, но он становится настолько длинным, когда вам нужно делать

VARIABLE1, VARIABLE2, VARIABLE3, VARIABLE3, VARIABLE4, VARIABLE5, VARIABLE6, VARIABLE7, VARIABLE8, ... , VARIABLE14 = range(14)

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

VARIABLE1,
VARIABLE2,
VARIABLE3,
...
VARIABLE14 = range(14)

Как я мог бы выполнить это самым простым способом?

4b9b3361

Ответ 1

О, ничего себе, я просто добавил скобки вокруг переменных и работал

(VARIABLE1,
VARIABLE2,
VARIABLE3,
...
VARIABLE14) = range(14)

Ответ 2

Вместо ручной настройки VARIABLE1, VARIABLE2... вы можете сделать это:

>>> for x in range(1, 15):
        globals()['VARIABLE{0}'.format(x)] = x

Делает то, что вы хотите, без лишних усилий печатать VARIABLE1... VARIABLE 14.

Ответ 3

Используя новую библиотеку aenum и Python 3 вы можете сделать:

from aenum import Enum

class SomeEnum(Enum, start=0):
    VARIABLE1
    VARIABLE2
    VARIABLE3
    VARIABLE4
    VARIABLE5
    VARIABLE6
    VARIABLE7
    VARIABLE8
    VARIABLE9
    VARIABLE10
    VARIABLE11
    VARIABLE12
    VARIABLE13
    VARIABLE14

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

>>> SomeEnum.VARIABLE7
<SomeEnum.VARIABLE7: 6>

Примечание: aenum записывается автором enum34

Ответ 4

Реализация перечисления, аналогичная 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))

Использование

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

Ответ 5

Явным способом объединения строк является использование символов обратной косой черты:

VARIABLE1,\
VARIABLE2,\
VARIABLE3,\
...
VARIABLE14) = range(14)

и неявный способ заключить в круглые скобки, квадратные скобки или фигурные скобки:

[VARIABLE1,
 VARIABLE2,
 VARIABLE3,
 ...
 VARIABLE14] = range(14)

Ответ 6

Изучив немного о функции диапазона, вы можете исправить ее в кратчайшие сроки. Посетите документацию для получения более подробной информации. Мы видим, что 2 apis (s): Диапазон (стоп) диапазон (начало, останов [, шаг])

Здесь он просто возвращает список номеров в этом конкретном диапазоне с шагом, который по умолчанию равен 1.

Следовательно, вам просто нужно убедиться, что ваш код соответствует тому, что вы можете сделать, явно указав python, что они находятся в той же строке, которую вы можете сделать, добавив символ "\" в конце каждой строки. Кроме того, если вы заключите их под символом "[]" или "(" ), обозначив их как список кортежей, интерпретатор python будет неявно рассматривать его как одну строку. Используйте перечисленные коды или поэкспериментируйте, чтобы узнать больше об этом.

Ответ 7

Создайте идентификаторы (переменную) как строки, такие как 'VARIABLE{}'.format(1), и создайте ген xp, который yield 2-element tuple состоит из идентификатора и значения типа ('VARIABLE1', 0).

Этот ген xp может использоваться для подачи dict или dict.update. В случае OP тег dict - тот, который возвращается globals().

>>> globals().update(('VARIABLE{}'.format(x+1), x) for x in range(14))
>>> VARIABLE1
0
>>> VARIABLE14
13

Если назначенные значения являются нецелыми, enumerate может решить проблему имен переменных.

>>> globals().update(('VARIABLE{}'.format(i), x) for i, x in enumerate('abcdefghijklmn',1))
>>> VARIABLE1
'a'
>>> VARIABLE14
'n'

Ответ 8

Я считаю, что словари часто бывают более подходящими, чем перечисления, поскольку они позволяют легко отображать целые числа в несколько переменных, функцию и т.д. Например, назначая функцию in и string:

import numpy as np,

CC = [(np.sin, "Taking the sine"),
      (np.cos, "Taking the cosine"),
      (np.tan, "Taking the tangens")]
dCC = dict(enumerate(CC, start=1))  # built the enumerated dictionary


def calc(n, x):
    """ Perform operation on `x` defined by number `n` """
    f, s = dCC[n]  # map number to function and string
    y = f(x)
    print(s + " from %g results in %g" % (x, y))
    return y

y = calc(2, np.pi)  # prints: "Taking the tangens from 3.14159 results in -1"