__getitem__ method on (meta)classes

R

Ron Garret

Steven Bethard said:
So then you don't necessarily need that type(v) == e1, you just need
type(v) != str. How about:

[xnip]

That's not bad. This conflates all enumerated items into a single
namespace whereas the metaclass solution makes each enumeration its own
namespace. For example:

plumbers = enum['Fred','John','Bill']
electricians = enum['Fred','Jake','Lester']

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.

Must sleep on it.

rg
 
S

Steven Bethard

Ron said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top