Skip to content

Instantly share code, notes, and snippets.

@ruiwen
Last active October 5, 2015 07:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruiwen/9343637 to your computer and use it in GitHub Desktop.
Save ruiwen/9343637 to your computer and use it in GitHub Desktop.
Enums
function Enum() {
var self = this;
var vals = {};
for(var i=0; i < arguments.length; ++i) {
vals[arguments[i]] = i == 0? 0 : Math.pow(2, i-1)
vals[i] = i == 0? 0 : Math.pow(2, i-1)
Object.defineProperty(self, arguments[i], {
'value': vals[arguments[i]],
})
}
return self
}
def enum(*sequential, **named):
'''
Easy enums in Python 2.x
Borrowed from http://stackoverflow.com/a/1695250
Metaclass idea from http://stackoverflow.com/a/6970831
Enum values map to integers in a log^2 scale, ie. 0, 1, 2, 4, 8 etc.
Enum class is also hardened against modification through overriding of the
__setattr__ and __setitem__ methods
>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1
Sequential mode is also supported
>>> Numbers = enum('ZERO', 'ONE', 'TWO', sequential=True)
>>> Numbers.ZERO
1
>>> Numbers.ONE
2
>>> Numbers.TWO
3
Manual mode
>>> Numbers = enum(A=123, B=456, C=789)
>>> Numbers.A
123
>>> Numbers.B
456
>>> Numbers.C
789
A mixture of the two modes is also supposed
>>> Numbers = enum(A, B, C=123)
>>> Numbers.A
0
>>> Numbers.B
1
>>> Numbers.C
123
Also
>>> Numbers = enum(A, B, C=123, sequential=True)
>>> Numbers.A
1
>>> Numbers.B
2
>>> Numbers.C
123
'''
items = {}
kwargs = {}
for k, v in named.iteritems():
if k[0].isupper():
items[k] = v
else:
kwargs[k] = v
seq = bool(kwargs.get('sequential'))
if seq:
enums = dict(zip(sequential, range(1, len(sequential)+1)), **items)
else:
enums = dict(zip(sequential, map(lambda x: 2 ** (x - 1) if x > 0 else 0, range(len(sequential)))), **items)
reverse = dict((value, key) for key, value in enums.iteritems())
def not_implemented():
raise NotImplementedError()
def normalise(self, k):
k = k.upper() if isinstance(k, basestring) else k
return k if k in self and k in enums.values() else enums[k]
meta = type('EnumMeta', (type,), {
"__contains__": lambda self, v: v in enums.keys() or v in enums.values(), # self.__dict__,
"__len__": lambda self: len(sequential),
"__getitem__": lambda self, k: normalise(self, k),
"__setattr__": lambda self, k, v: not_implemented(),
"__setitem__": lambda self, k, v: not_implemented(),
"__iter__": lambda self: iter(reverse.items()),
"items": lambda self: reverse.items()
})
d = {}
d.update(enums)
return meta('Enum', (object,), d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment