Saturday, March 19, 2016

Python Multi-lined Artificial enums using range

Leave a Comment

I am trying to make an enum-type class in Python but it gets so lengthly when you have to do

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

and I've tried to set it up like the following, but ended up not working.

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

How would I accomplish this in the simplest way possible?

8 Answers

Answers 1

Oh, wow I just added brackets around the variables and it worked

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

Answers 2

Instead of manually typing VARIABLE1, VARIABLE2 ... you can do this:

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

Does what you want, without the extra effort of typing VARIABLE1 ... VARIABLE 14.

Answers 3

Using the new aenum library and Python 3 you can do:

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

and in use looks like:

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

Note: aenum is written by the author of enum34

Answers 4

The explicit way of line joining is to use backslash characters:

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

and the implicit way is to enclose with parentheses, square brackets or curly braces:

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

Answers 5

An enum implementation similar to namedtuple using namedtuple. This enum function creates a class with namedtuple and instantiates the class with supplied arguments. Arguments are strings, tuple or list. The tuple or list form of arguments are used to supply a value to the constants thus resetting value sequence. By default, constants are valued starting from zero.

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 

Answers 6

By learning a bit about range function you can fix it in no time. Visit - documentation for more details. We see that the 2 apis(s) are: range(stop) range(start, stop[, step])

Where it just returns a list of numbers in that particular range with step which is 1 by default.

Hence you just need to make sure that your code is compliant with that which you can do by explicitly telling python that they are the in the same line which you can do by adding '\' character at the end of every line. Also if you enclose them by '[]' or '()' marking them as list of tuple, the python interpreter will implicitly treat it as a one line. Use the codes listed or experiment yourself to get more hang of it.

Answers 7

Build the identifiers (variable) as strings like 'VARIABLE{}'.format(1) and make a genexp which yields 2-element tuples consisting of the identifier and the value like ('VARIABLE1', 0).

This genexp can be used to feed a dict or dict.update. In The OP's case the dict is the one returned by globals().

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

If the values to be assigned are non-integers enumerate can solve the problem of variable naming.

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

Answers 8

I find dictionaries often to be more suitable than enums, because they allow to easily map integers to more than one variable, function etc. For example assigning an in to a function and 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" 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment