Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #102926 > unrolled thread
| Started by | Herman <sorsorday@gmail.com> |
|---|---|
| First post | 2016-02-14 16:17 -0800 |
| Last post | 2016-02-15 21:28 +1300 |
| Articles | 3 — 3 participants |
Back to article view | Back to comp.lang.python
How to properly override the default factory of defaultdict? Herman <sorsorday@gmail.com> - 2016-02-14 16:17 -0800
Re: How to properly override the default factory of defaultdict? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-02-15 14:56 +1100
Re: How to properly override the default factory of defaultdict? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-02-15 21:28 +1300
| From | Herman <sorsorday@gmail.com> |
|---|---|
| Date | 2016-02-14 16:17 -0800 |
| Subject | How to properly override the default factory of defaultdict? |
| Message-ID | <mailman.122.1455495511.22075.python-list@python.org> |
I want to pass in the key to the default_factory of defaultdict and I found
that defaultdict somehow can intercept my call to dict.__getitem__(self,
key), so my class's __getitem__ have to catch a TypeError instead instead
of KeyError. The following class is my code:
class DefaultDictWithEnhancedFactory(defaultdict):
"""Just like the standard python collections.dict,
but the default_factory takes the missing key as argument.
Args:
default_factory: A function that takes the missing key as the
argument
and return a value for the missing key.
*a: arguments passing to the defaultdict constructor
**kw: keyword arguments passing to the defaultdict constructor
"""
def __init__(self, default_factory, *a, **kw):
defaultdict.__init__(self, default_factory, *a, **kw)
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
# Normally, you would expect this line to be
# called for missing keys...
return self.default_factory(key)
except TypeError as ex:
# However, this is actually getting called
# because for some reason, defaultdict still
# intercepts the __getitem__ call and raises:
# TypeError: <lambda>() takes exactly 1 argument (0 given)
# So we have to catch that instead...
if "lambda" in str(ex):
return self.default_factory(key)
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2016-02-15 14:56 +1100 |
| Message-ID | <56c14c74$0$1500$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #102926 |
On Monday 15 February 2016 11:17, Herman wrote:
> I want to pass in the key to the default_factory of defaultdict
Just use a regular dict and define __missing__:
class MyDefaultDict(dict):
def __missing__(self, key):
return "We gotcha key %r right here!" % key
If you want a per-instance __missing__, do something like this:
class MyDefaultDict(dict):
def __init__(self, factory):
self._factory = factory
def __missing__(self, key):
return self._factory(self, key)
d = MyDefaultDict(lambda self, key: ...)
--
Steve
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2016-02-15 21:28 +1300 |
| Message-ID | <didgheFteu2U1@mid.individual.net> |
| In reply to | #102926 |
Herman wrote: > I want to pass in the key to the default_factory of defaultdict and I found > that defaultdict somehow can intercept my call to dict.__getitem__(self, > key), What's happening here is that defaultdict doesn't actually override __getitem__ at all. Instead, it overrides __missing__, which gets called by the standard dict's __getitem__ for a missing key. As Steven said, you don't need a defaultdict here at all, just a dict subclass that defines __missing__ the way you want. -- Greg
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web