Using tuples correctly?
Bengt Richter
bokr at oz.net
Mon Oct 11 04:13:44 EDT 2004
On Mon, 11 Oct 2004 05:53:47 +0200, =?ISO-8859-1?Q?BJ=F6rn_Lindqvist?= <bjourne at gmail.com> wrote:
>I like tuples alot. But in some situations you seem to be forced to
>access the elements of a tuple via its indexes and that is pretty
>ugly. For example:
>
># make_color() returns a rgb tuple (r, g, b). I.e. (255, 0, 0)
>print "The red value is: ", make_color()[0]
>
>Not nice at all. It is maybe OK for a rgb tuple that only has three
>elements, but for a tuple that has 10+ elements, index access is
>rediculous. In that case, unpacking wont helpe either. What you would
>like to write is:
>
>print "The red value is: ", make_color().r
>
>You can get that to work by using this recipe
>http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/218485 from
>the Python Cookbook. Then write this:
>
>Color =3D superTuple("Color", ["r", "g", "b"])
>def make_color():
> return Color(12, 24, 48)
>
>However, then make_color has to assume that there already exists a
>special tuple type named Color. But that assumption is bad and you
>shouldn't need to assume it. You could also write
Why is that bad? You only have to define it once.
>
>return superTuple("Color", ["r", "g", "b"])(12, 24, 48)
>
>To create the tuple type and instantiate it at the same type. But it
>is alot to write. You could trim it down to: st("r", "g", "b")(12, 24,
>48) if you want to save your fingers. Still to much and looks kinda
>awkward.
How about
return Color(12, 24, 48, order='r g b')
or
Color.names = 'r g b'.split() # override names for all instances that don't have order=
... # above is not even necessary, since that's the initial names value
return Color(g=24, r=12, b=48) # use names to assign ordered values
or
return Color() # put zeroes for unspecified values to match names length
etc. See below
>
>After some more browsing of the Python Cookbook and googling it seems
>like lots of people is trying to emulate structs on the fly in python.
>So why aren't there a tuple-with-named-attributes type in python? So
>you could write stuff like this:
>
>return (r: 10, g: 20, b: 30) or maybe return (.r 10, .g 20, .b 30)
>
>Clearly, I must be thinking wrong or it would already be implemented
>in python. Atleast there would have been a PEP for it. Maybe I'm just
>using tuples incorrectly and that is why my code uses index access to
>tuples? Someone must have already thought about this and they must
>have discussed it and quickly realized that this is A Very Bad Thing.
>But why? I'm new, so please dont get to angry if the answer is
>obvious.
>
Not sure what you are needing, but consider yet another class:
(not a speed demon, and not tested beyond what you see below ;-)
>>> class Color(tuple):
... names = 'r g b'.split()
... def __new__(cls, *args, **kw):
... values = list(args)
... onames = kw.get('order','').split()
... names = onames or cls.names
... if len(names)>len(values): values.extend([0]*(len(names)-len(values)))
... assert len(names)<=len(values)
... for i, name in enumerate(names):
... if name in kw: values[i] = kw.get(name)
... inst = tuple.__new__(cls, values)
... if onames: inst.names=onames
... return inst
... def __getattr__(self, name):
... try: i = object.__getattribute__(self, 'names').index(name)
... except ValueError: raise AttributeError, 'No component named %r'%name
... return tuple.__getitem__(self, i)
...
>>> rgb = Color(1,2,3)
>>> rgb
(1, 2, 3)
>>> rgb.b, rgb.g, rgb.r #in reverse
(3, 2, 1)
>>> c0 = Color()
>>> c0
(0, 0, 0)
>>> zip(c0.names, c0)
[('r', 0), ('g', 0), ('b', 0)]
>>> c2 = Color(b=33,g=22)
>>> c2
(0, 22, 33)
>>> c3 = Color(red=111, alpha=.5, order='alpha red green blue')
>>> c3
(0.5, 111, 0, 0)
>>> rgb
(1, 2, 3)
>>> rgb.g
2
>>> c3.green
0
>>> c3.alpha
0.5
Maybe some ideas for what you really want ?;-)
Probably overlaps other super-tuples a fair amount. I didn't look.
Regards,
Bengt Richter
More information about the Python-list
mailing list