[Python-Dev] from tuples to immutable dicts (original) (raw)
Armin Rigo arigo@tunes.org
Sat, 23 Nov 2002 02:32:46 -0800 (PST)
- Previous message: [Python-Dev] Half-baked proposal: * (and **?) in assignments
- Next message: [Python-Dev] from tuples to immutable dicts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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:
use 'tuple' or a new subtype 'namedtuple' or 'structure'?
the suggested syntax emphasis the use of strings for the keys, but the constructor could be more general, taking arbitrary hashable values:
t = namedtuple([(1,2), (3,4)]) t = namedtuple({1:2, 3:4}) dict(t) does not work: confusion with dict() of a sequence of pairs dict(**t) -> {1:2, 3:4} # based on Just's idea of extra keyword arguments to dict()
how do we read the key names? It seems impossible to add methods to namedtuples since all attributes should potentially be reserved for item reads. Some bad ideas:
p = (1, 2, x=3, y=4) p.keys() -> [None, None, 'x', 'y'] # special method name p.key(2) -> 'x' or p.keys -> (None, None, 'x', 'y') # special attribute or p % 2 -> 'x' # new operator (abusing % again) or iterkeys(p) -> iterable # global function (urgh)
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.
shoud name collisions be allowed inside a namedtuple?
what about * and ** call syntaxes? For compatibility we might have to do
p = (1, 2, x=3, y=4) f(*p) # treat p as a tuple, always ignoring names (?) f(**p) # only uses the named items of p (??) f(***p) # same as f(1, 2, x=3, y=4)
or maybe push forward a shorter form of *** and deprecate * and **...?
- dissymetries between namedtuples and dicts: operations like 'in' and iteration operates on values in tuples, but on keys in dicts...
Armin.
- Previous message: [Python-Dev] Half-baked proposal: * (and **?) in assignments
- Next message: [Python-Dev] from tuples to immutable dicts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]