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.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4