[Python-Dev] from tuples to immutable dicts (original) (raw)

Armin Rigo arigo@tunes.org
Sat, 23 Nov 2002 02:32:46 -0800 (PST)


Hello everybody,

There are some (admittedly occasional) situations in which an immutable dictionary-like type would be handy, e.g. in the C core to implement switches or to speed up keyword argument matching.

Here is a related suggestion: enhancing or subclassing tuples to allow items to be named. Example syntax:

(1,2,c=3,d=4)

would build the 4-tuple (1,2,3,4) with names on the last two items.

I believe that it fills a hole between very small structures (e.g. (x,y) coordinates for points) and large structures naturally implemented as classes: it allows small structures to grow a bit without turning into an obscure 5- or 10-tuple. As a typical example, consider the os.stat() trick: it currently returns an object that behaves like a 10-tuple, but whose items can also be read via attributes for the sake of clarity. It only seems natural to be allowed to do:

p = (x=2, y=3)
print p.x          # 2
print p[-1]        # 3
print list(p)      # [2,3]

Of course, the syntax to build such tuples is chosen to match the call syntax. Conversely, tuple unpacking could use exactly the same syntax as function argument lists:

x = (1, 2)
(a, b, c=3) = x             # set a=1, b=2, c=3
a, b, c = (b=2, c=3, a=1)   # idem

The notion might unify the two special * and ** arguments, which are set respectively to an immutable list and a mutable new dictionary. A single special argument (***?) might be used to get the extra arguments as a tuple with possibly named items. As a side effect the function can know in which order the keyword arguments were passed in, which may or may not be a good idea a priori but which I sometimes wish I could do.

def f(x, ***rest):
    print rest

f(1,2,3)        # -> (2, 3)
f(1,2,c=3,d=4)  # -> (2, c=3, d=4)
f(1,2,x=3,y=4)  # -> TypeError ('x' gets two values)
f(w=1,x=2,y=3)  # -> (w=1, y=3)

Questions:

Note that dict(p) -> {'x': 3, 'y': 4} is a partial solution, but it makes inspection heavier and looses all info about key order and unnamed items. Besides, dict((1,2,3)) -> {} looks like a bad thing to do.

or maybe push forward a shorter form of *** and deprecate * and **...?

Armin.