Python中关于__missing__方法的使用问题

在网上看到这么一道问题。当给定以下字典的子类,下面的代码能运行么,为什么? 
class D(dict): 
        def __missing__(self,key): 
                return[] 

d=D() d[‘f’]=12

网上给出的答案是可以运行,因为当 key 缺失时,执行 DefaultDict 类,字典的实例将自动实例化这个数列。 但是,我自己试着下了下面的代码,结果发现也能运行,所以不是很理解上面答案想说明什么,以及上面这道题目想考察的点是什么?恳请大家指点,感谢

class E(dict): pass

e=E() e[‘f’]=13


Python中关于__missing__方法的使用问题

10 回复

不知道它想考察什么
只有从字典里取值的时候才会有 key 缺失的情况。。。


__missing__是给dict子类用的,当通过d[key]访问不存在的键时,Python会调用这个方法。它接收一个参数(就是那个不存在的key),然后你返回一个值作为这个key对应的结果,同时这个键值对不会真的被添加到字典里。

看个具体例子就明白了:

class DefaultDict(dict):
    def __missing__(self, key):
        # 当访问不存在的key时,返回0
        return 0

d = DefaultDict({'a': 1, 'b': 2})
print(d['a'])  # 1 - 正常访问
print(d['c'])  # 0 - 调用__missing__返回0
print(d)       # {'a': 1, 'b': 2} - c没有被添加进去

# 如果你想让访问后自动添加,可以在__missing__里设置
class AutoDict(dict):
    def __missing__(self, key):
        value = len(key)  # 随便搞个默认值
        self[key] = value  # 手动添加
        return value

ad = AutoDict()
print(ad['hello'])  # 5
print(ad)           # {'hello': 5} - 这次被添加了

关键点:

  1. 只对dict子类有效,普通字典没这功能
  2. 只在d[key]这种下标访问时触发,d.get(key)不会调用
  3. 默认不自动添加键值对,需要的话得手动self[key]=value

这玩意儿在实现缓存、默认值字典时挺有用的。简单说就是给字典访问加个“兜底”逻辑。

??
d[‘f’]=12 难道不是赋值吗

你直接 打印 e[‘f’] 就会报错了 d[‘f’]的话会显示 []

有时候为了方便起见,就算某个键在映射里不存在,希望在通过这个键读取值的时候能得到一个默认值。有两个途径能帮我们达到这个目的,一个是通过 defaultdict,另一个是给自己定义一个 dict 的子类,然后在子类中实现__missing__ 方法。


非常感谢!

楼主有兴趣可以深究一下 missing 在哪调用? get 方法也可以获取值,但是为啥不同于 getitem 函数?四楼基本上解决了楼主的问题

https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
文档里讲的很清楚啊,你那个是在 dict 中添加东西了,如果光是 e[‘ f ’],因为你没有写__missing__(),所以会抛出一个 keyerror,如果有__missing__(),那就返回或者抛出你在 missing 里写东西啊,其实还有一种简单的方法,就是 get(key[, default]),如果找不到 key 就返回 default,默认是 None。一个简单的字典缓存装饰器就可以用:
def buffer(fn):
cache = {}
miss = object()

(fn)
def wrapper(*args):
result = cache.get(args, miss)
if result is miss:
result = fn(*args)
cache[args] = result
return result

return wrapper

谢谢指点,我专门去查了__missing__、__get__和__getitem__的说明,涨知识了!

谢谢指点!

回到顶部