Using a metaclass allows you to distinguish Fred the plumber from Fred the electrician. But that may or may not be what one actually wants.
Not sure what you mean here. The non metaclass solution still has separate enum.item objects for each new enum. Consider your implementation:
py> def enum(vals): ... class enum(object): ... class __metaclass__(type): ... def __getitem__(self, index): ... return self.vals[index] ... def __init__(self, val): ... try: ... self.val = type(self).vals.index(val) ... except: ... raise TypeError('%s is not a valid %s' % ... (val, type(self).__name__)) ... enum.vals = vals ... return enum ... py> plumbers = enum(['Fred','John','Bill']) py> electricians = enum(['Fred','Jake','Lester']) py> plumbers[0] == electricians[0] True py> plumbers('Fred') == electricians('Fred') False py> plumbers[0], electricians[0] ('Fred', 'Fred') py> plumbers('Fred'), electricians('Fred') (<__main__.enum object at 0x0115D530>, <__main__.enum object at 0x01162D50>)
Note that your implementation conflates plumbers[0] and electricians[0] (because your __getitem__ returns the string, not an enum object). Not sure if this is the intended behavior, but it seems a little weird to me. OTOH, plumbers('Fred') and electricians('Fred') are not conflated.
Now consider my implementation:
py> class enum(object): ... class item(object): ... def __init__(self, val): ... self.val = val ... def __init__(self, vals): ... self.items = [type(self).item(val) for val in vals] ... self._val_item_map = dict(zip(vals, self.items)) ... def __call__(self, val): ... try: ... return self._val_item_map[val] ... except KeyError: ... raise TypeError('%s is not a valid %s' ... (val, type(self))) ... def __getitem__(self, index): ... return self.items[index] ... def __iter__(self): ... return iter(self.items) ... py> plumbers = enum(['Fred','John','Bill']) py> electricians = enum(['Fred','Jake','Lester']) py> plumbers[0] == electricians[0] False py> plumbers('Fred') == electricians('Fred') False py> plumbers[0], electricians[0] (<__main__.item object at 0x011627F0>, <__main__.item object at 0x011883B0>) py> plumbers('Fred'), electricians('Fred') (<__main__.item object at 0x011627F0>, <__main__.item object at 0x011883B0>)
Note that Fred the plumber and Fred the electrician always compare as inequal (using either __call__ or __getitem__). Isn't this "allowing you to distinguish Fred the plumber from Fred the electrician"?
STeVe -- http://mail.python.org/mailman/listinfo/python-list