Trying to create a custom case insensitive dictionary, I received the following uncomfortable and (from my point of view) unexpected actions. If you deduce a class from a dict , the overloaded functions __iter__ , keys , values ignored when accessing the dict . I shortened it to the following test case:
import collections class Dict(dict): def __init__(self): super(Dict, self).__init__(x = 1) def __getitem__(self, key): return 2 def values(self): return 3 def __iter__(self): yield 'y' def keys(self): return 'z' if hasattr(collections.MutableMapping, 'items'): items = collections.MutableMapping.items if hasattr(collections.MutableMapping, 'iteritems'): iteritems = collections.MutableMapping.iteritems d = Dict() print(dict(d))
The values ββfor keys , values and __iter__ , __getitem__ are incompatible only to demonstrate which methods are actually called.
The documentation for dict.__init__ states:
If a positional argument is given and it is the object of comparison, the dictionary is created with the same key-value pairs as the display object. Otherwise, the positional argument must be an iterator object.
I suppose this has something to do with the first sentence, and possibly with optimizations for the built-in dictionaries.
Why is the dict(d) call not used in any of the keys , __iter__ ? Is it possible to overload the "mapping" in some way to force the dict constructor to use my presentation of key-value pairs?
Why did I use this? For case insensitive but containing a dictionary, I wanted:
- store (lowercase => (original_case, value)) inside while it is displayed as (any_case => value).
- derives from a
dict for working with some external library code that uses isinstance checks - don't use 2 dictionary searches: lower_case => original_case and then the value of original_case => (this is the solution I'm doing now)
If you are interested in the application case: here is the corresponding branch