1

Say you have a dict called mydict defined below, and you look for a key called 'D'.

mydict = {'A':'a',
          'B':'b',
          'C':'c'}
mydict['D']

The desired output should be 'D', the exact output you entered. Is there a way to do this with default dict?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 8
    `x = myDict.get('D', 'D')` ? – azro Dec 30 '21 at 22:29
  • 5
    `defaultdict` is the name of a Python `dict` subclass (see [documentation](https://docs.python.org/3/library/collections.html#collections.defaultdict))— it's doesn't do what you think, so don't use that term. You can easily create your own subclass that does what you want. – martineau Dec 30 '21 at 22:32

2 Answers2

5

As I mentioned in a comment, you can define your own dictionary subclass that does what you want (simply echos missing keys — it doesn't add them):

class MyDefaultDict(dict):
    def __missing__(self, key):
        return key


mydict = MyDefaultDict({'A':'a',
                        'B':'b',
                        'C':'c'})

print(f"{mydict['D']=}")  # -> mydict['D']='D'

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    Was all set to suggest overriding `__getitem__()`, but this is so much nicer. – Mark Dec 30 '21 at 22:41
  • 3
    Micro-optimization for when it matters: Remove the `self` argument (since you use it for nothing), and decorate the definition of `__missing__` with `@staticmethod`. Reduces cost of looking up missing keys by ~25% (tested on CPython 3.9.7 running on Alpine Linux under WSLv2). – ShadowRanger Dec 30 '21 at 22:45
  • 2
    @Mark: Yeah, the made this hook precisely to allow `dict` subclasses (e.g. `Counter`, `defaultdict`) to handle missing keys without slowing down the core code path for key lookup. `dict`'s default `__getitem__` is what invokes `__missing__` when the lookup fails as a fallback option before raising a `KeyError`. – ShadowRanger Dec 30 '21 at 22:47
  • 1
    @ShadowRanger: Interesting, but not something I would mention in answer to a basic question like this — and besides, you know what they say about premature optimization… – martineau Dec 30 '21 at 22:49
4

A collection.defaultdict is used to get a factory for values, so when setting a pair, nor when getting it

Just use dict.get

mydict = {'A':'a','B':'b','C':'c'}
print(mydict.get('A', 'A'))  # a
print(mydict.get('D', 'D'))  # D
azro
  • 53,056
  • 7
  • 34
  • 70