get和dunder getitem之间的区别

bvm*_*ode 8 python python-3.x

我正在阅读Fluent Python并试图更深入地理解字典.

因此,当我运行以下内容时,结果很容易理解,get()和dunder getitem()都返回相同的结果

sample = {'a':1, 'b':2}
print(sample.__getitem__('a')) # 1
print(sample.get('a')) # 1
Run Code Online (Sandbox Code Playgroud)

当我用get()子类化dict时,我得到一个工作实例

class MyDict(dict):
    def __missing__(self, key):
        return 0

    def get(self, key):
        return self[key]

d = MyDict(sample)
print(d['a']) # 1
print(d['c']) # 0
Run Code Online (Sandbox Code Playgroud)

现在,如果我用dunder getitem()替换get(),我会收到一个错误,我不确定为什么.

class MyDict2(dict):
    def __missing__(self, key):
        return 0

    def __getitem__(self, key):
        return self[key]

d = MyDict2(sample)
print(d['a'])
print(d['c'])
Run Code Online (Sandbox Code Playgroud)

错误

RecursionError: maximum recursion depth exceeded while calling a Python object
Run Code Online (Sandbox Code Playgroud)

所以问题是,在这种情况下get和dunder getitem有什么区别,为什么会导致递归错误?

Jea*_*bre 6

def __getitem__(self, key):
    return self[key]
Run Code Online (Sandbox Code Playgroud)

self[key]调用最低级别__getitem__调用self[key]...无限递归.

在:

def get(self, key):
    return self[key]
Run Code Online (Sandbox Code Playgroud)

self[key]__getitem__dict类中调用最低级别,因此它不会递归:它可以工作(你只是重载了get方法,就是全部)


AGN*_*zer 5

那是因为self[key]inMyDict2.__getitem__(key)等价于(即调用)self.__getitem__(key)=> 无限递归。