Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It's funny, I just had a need for this the other day and I couldnt find an implementation worth using... so I wrote my own:</p> <pre><code>import functools class EnumValue(object): def __init__(self,name,value,type): self.__value=value self.__name=name self.Type=type def __str__(self): return self.__name def __repr__(self):#2.6 only... so change to what ever you need... return '{cls}({0!r},{1!r},{2})'.format(self.__name,self.__value,self.Type.__name__,cls=type(self).__name__) def __hash__(self): return hash(self.__value) def __nonzero__(self): return bool(self.__value) def __cmp__(self,other): if isinstance(other,EnumValue): return cmp(self.__value,other.__value) else: return cmp(self.__value,other)#hopefully their the same type... but who cares? def __or__(self,other): if other is None: return self elif type(self) is not type(other): raise TypeError() return EnumValue('{0.Name} | {1.Name}'.format(self,other),self.Value|other.Value,self.Type) def __and__(self,other): if other is None: return self elif type(self) is not type(other): raise TypeError() return EnumValue('{0.Name} &amp; {1.Name}'.format(self,other),self.Value&amp;other.Value,self.Type) def __contains__(self,other): if self.Value==other.Value: return True return bool(self&amp;other) def __invert__(self): enumerables=self.Type.__enumerables__ return functools.reduce(EnumValue.__or__,(enum for enum in enumerables.itervalues() if enum not in self)) @property def Name(self): return self.__name @property def Value(self): return self.__value class EnumMeta(type): @staticmethod def __addToReverseLookup(rev,value,newKeys,nextIter,force=True): if value in rev: forced,items=rev.get(value,(force,()) ) if forced and force: #value was forced, so just append rev[value]=(True,items+newKeys) elif not forced:#move it to a new spot next=nextIter.next() EnumMeta.__addToReverseLookup(rev,next,items,nextIter,False) rev[value]=(force,newKeys) else: #not forcing this value next = nextIter.next() EnumMeta.__addToReverseLookup(rev,next,newKeys,nextIter,False) rev[value]=(force,newKeys) else:#set it and forget it rev[value]=(force,newKeys) return value def __init__(cls,name,bases,atts): classVars=vars(cls) enums = classVars.get('__enumerables__',None) nextIter = getattr(cls,'__nextitr__',itertools.count)() reverseLookup={} values={} if enums is not None: #build reverse lookup for item in enums: if isinstance(item,(tuple,list)): items=list(item) value=items.pop() EnumMeta.__addToReverseLookup(reverseLookup,value,tuple(map(str,items)),nextIter) else: value=nextIter.next() value=EnumMeta.__addToReverseLookup(reverseLookup,value,(str(item),),nextIter,False)#add it to the reverse lookup, but don't force it to that value #build values and clean up reverse lookup for value,fkeys in reverseLookup.iteritems(): f,keys=fkeys for key in keys: enum=EnumValue(key,value,cls) setattr(cls,key,enum) values[key]=enum reverseLookup[value]=tuple(val for val in values.itervalues() if val.Value == value) setattr(cls,'__reverseLookup__',reverseLookup) setattr(cls,'__enumerables__',values) setattr(cls,'_Max',max([key for key in reverseLookup] or [0])) return super(EnumMeta,cls).__init__(name,bases,atts) def __iter__(cls): for enum in cls.__enumerables__.itervalues(): yield enum def GetEnumByName(cls,name): return cls.__enumerables__.get(name,None) def GetEnumByValue(cls,value): return cls.__reverseLookup__.get(value,(None,))[0] class Enum(object): __metaclass__=EnumMeta __enumerables__=None class FlagEnum(Enum): @staticmethod def __nextitr__(): yield 0 for val in itertools.count(): yield 2**val def enum(name,*args): return EnumMeta(name,(Enum,),dict(__enumerables__=args)) </code></pre> <p>Take it or leave it, it did what I needed it to do :)</p> <p>Use it like:</p> <pre><code>class Air(FlagEnum): __enumerables__=('None','Oxygen','Nitrogen','Hydrogen') class Mammals(Enum): __enumerables__=('Bat','Whale',('Dog','Puppy',1),'Cat') Bool = enum('Bool','Yes',('No',0)) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload