default behavior

John Posner jjposner at optimum.net
Tue Aug 3 22:49:06 EDT 2010


On 8/3/2010 6:48 PM, Ethan Furman wrote:
> Christian Heimes wrote:
>>> I just went and read the entry that had the bogus claim --
>>> personally, I didn't see any confusion. I would like to point out the
>>> __missing__ is *not* part of dicts (tested on 2.5 and 2.6 -- don't
>>> have 2.7 installed yet).
>>
>> I beg your pardon but you are wrong. __missing__ is available for all
>> *subclasses* of dict since Python 2.5. See
>> http://svn.python.org/view/python/branches/release25-maint/Objects/dictobject.c?revision=81031&view=markup
>>
>>
>>>>> class mydict(dict):
>> ... def __missing__(self, key):
>> ... print "__missing__", key
>> ... raise KeyError(key)
>> ...
>>>>> m = mydict()
>>>>> m[1]
>> __missing__ 1
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> File "<stdin>", line 4, in __missing__
>> KeyError: 1
>
> Perhaps punctuation will help clarify my intent:
>
> __missing__ is *not* part of (dict)s, as shown by dir(dict()):
>
> ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__',
> '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__',
> '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__',
> '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
> '__repr__', '__setattr__', '__setitem__', '__str__', 'clear', 'copy',
> 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys',
> 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update',
> 'values']
>
> And, just to state what is hopefully obvious, if you don't create
> __missing__ yourself, it still isn't in the subclass:

Right, a __missing__ method does not magically appear in the subclass. 
Rather, the subclass is allowed (but not required) to define a method 
named __missing__, which will "magically" be called in certain situations.

Here's a dict subclass that uses the "magic" for a purpose that has 
nothing to do with default values:

class BadKeyTrackerDict(dict):
     def __init__(self, *args, **kwargs):
         dict.__init__(self, *args, **kwargs)
         self.bad_keys = set([])

     def __missing__(self, key):
         """
         add missing key to "bad keys" set
         """
         self.bad_keys.add(key)
         raise KeyError

Note that "defaultdict" is nowhere in sight here. It's the dict class 
(or type) itself that provides the magic -- but only for its subclasses.

>
> --> class somedict(dict):
> ... "Is __missing__ defined if I don't define it? Nope."
> ...
> --> sd = somedict()
> --> sd[1]
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> KeyError: 1
> --> dir(sd)
> ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__',
> '__dict__', '__doc__', '__eq__', '__ge__', '__getattribute__',
> '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__',
> '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
> '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__str__',
> '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items',
> 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem',
> 'setdefault', 'update', 'values']
>
> ~Ethan~

-John



More information about the Python-list mailing list