On Wed, Jun 07, 2017 at 06:14:08PM +0000, Nick Humrich wrote: > It would be cool to have a syntax that would unpack the dictionary to > values based on the names of the variables. Something perhaps like: > > a, b, c = **mydict
This was discussed (briefly, to very little interest) in March/April 2008: https://mail.python.org/pipermail/python-ideas/2008-March/001511.html https://mail.python.org/pipermail/python-ideas/2008-April/001513.html and then again in 2016, when it spawned a very large thread starting here: https://mail.python.org/pipermail/python-ideas/2016-May/040430.html I know there's a lot of messages, but I STRONGLY encourage anyone, whether you are for or against this idea, to read the previous discussion before continuing it here. Guido was luke-warm about the **mapping syntax: https://mail.python.org/pipermail/python-ideas/2016-May/040466.html Nathan Schneider proposed making dict.values() take optional key names: https://mail.python.org/pipermail/python-ideas/2016-May/040517.html Guido suggested that this should be a different method: https://mail.python.org/pipermail/python-ideas/2016-May/040518.html My recollection is that the discussion evertually petered out with a more-or-less consensus that having a dict method (perhaps "getvalues"?) plus regular item unpacking is sufficient for the common use-case of unpacking a subset of keys: prefs = {'width': 80, 'height': 200, 'verbose': False, 'mode': PLAIN, 'name': 'Fnord', 'flags': spam|eggs|cheese, ... } # dict includes many more items width, height, size = prefs.getvalues( 'width', 'height', 'papersize', ) This trivially supports the cases where keys are not strings or valid identifiers: class_, spam, eggs = mapping.getvalues('class', 42, '~') It easily supports assignment targets which aren't simple variable names: obj.attribute[index], spam().attr = mapping.getvalues('foo', 'bar') An optional (defaults to False) "pop" keyword argument supports extracting and removing values from the dict in one call, which is commonly needed inside __init__ methods with **kwargs: class K(parent): def __init__(self, a, b, c, **kwargs): self.spam = kwargs.pop('spam') self.eggs = kwargs.pop('eggs') self.cheese = kwargs.pop('cheese') super().__init__(a, b, c, **kwargs) becomes: self.spam, self.eggs, self.cheese = kwargs.getvalues( 'spam eggs cheese'.split(), pop=True ) I don't recall this being proposed at the time, but we could support keyword arguments for missing or default values: DEFAULTS = {'height': 100, 'width': 50} prefs = get_prefs() # returns a dict height, width, size = prefs.getvalues( 'height', 'width', 'papersize', defaults=DEFAULTS, missing=None ) A basic implementation might be: # Untested. def getvalues(self, *keys, pop=False, defaults=None, missing=SENTINEL): values = [] for key in keys: try: x = self[key] except KeyError: if defaults is not None: x = defaults.get(key, SENTINEL) if x is SENTINEL: x = missing if x is SENTINEL: raise KeyError('missing key %r' % key) if pop: del self[key] values.append(x) return tuple(values) It's a bit repetitive for the common case where keys are the same as the assignment targets, but that's a hard problem to solve, and besides, "explicit is better than implicit". It also doesn't really work well for the case where you want to blindly create new assignment targets for *every* key, but: - my recollection is that nobody really came up with a convincing use-case for this (apologies if I missed any); - and if you really need this, you can do: locals().update(mapping) inside a class body or at the top-level of the module (but not inside a function). Please, let's save a lot of discussion here and now, and just read the 2016 thread: it is extremely comprehensive. -- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/