This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Bug in **kwds expansion on call?
Type: behavior Stage:
Components: Interpreter Core Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, rhettinger, terry.reedy
Priority: normal Keywords:

Created on 2010-06-08 19:10 by terry.reedy, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (4)
msg107338 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2010-06-08 19:10
In 2.6, the requirement for **kwds keyword argument expansion in calls (LangRef 5.3.4. Calls) is relaxed from "(subclass of) dictionary" (2.5) to "mapping".  The requirement in this context for 'mapping' is not specified. LRef3.2 merely says "The subscript notation a[k]  selects the item indexed by k from the mapping a;". Here, .keys seems to be needed in addition to .__getitem__. (.items alone does not make an object a mapping.)

In python-list thread "Which objects are expanded by double-star ** operator?", Peter Otten posted 2.6 results for

class A(object):
     def keys(self): return list("ab")
     def __getitem__(self, key):
         return 42
        
class B(dict):
     def keys(self): return list("ab")
     def __getitem__(self, key):
         return 42

def f(**kw):
     print(kw)

f(**A())
# {'a': 42, 'b': 42}

b = B(); print(b['a'], b['b']) # I added this
# 42, 42
f(**b)
# {}

I get same with 3.1. It appears .keys() is called in the first case, but not the second, possibly due to an internal optimization.

The different of outcome seems like a bug, though one could argue that the doc is so vague that it makes no promise to be broken.
msg107347 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2010-06-08 21:07
This falls under the usual category of dict subclasses not having their methods called. Especially since the B dict doesn't actually contain anything.
msg107366 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2010-06-08 23:59
Might that 'usual' fact be somehow documented? I am hard put to suggest anything since it is a fact I, like others, am not aware of. Is this a general rule for subclasses of builtins? or specific to dicts?
msg107370 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2010-06-09 00:17
Somewhere, we should document the-facts-of-life for subclassing builtins.

1) For the most part, C code has the pattern
       if isinstance(obj, some_builtin_type):
           call the built_type's methods directly using slotted methods
       otherwise:
           use slower getattribute style calls

2) A subclasser of a dict needs to actually populate the dict with the values they want used.   The built-in dict class is "open for extension and closed for modification" -- the open/closed principle.  This is necessary or else a subclasser could easily break the built-in type's invariants and crash python.

3) For the most part, only something like subclassing UserDict gives you full control.
History
Date User Action Args
2022-04-11 14:57:02adminsetgithub: 53191
2010-06-09 00:17:15rhettingersetnosy: + rhettinger
messages: + msg107370
2010-06-08 23:59:44terry.reedysetmessages: + msg107366
2010-06-08 21:07:18benjamin.petersonsetstatus: open -> closed

nosy: + benjamin.peterson
messages: + msg107347

resolution: not a bug
2010-06-08 19:10:41terry.reedycreate