Officially, CPython does not strictly dictate whether and when methods overridden in subclasses that inherit built-in types will be called implicitly.
Similarly, these methods are never called by other built-in methods of the same object.
For example, overridden in a subclass of dict __getitem__()
will not be get()
called by the built-in method.
The above situation is consistent in CPython and PyPy.
The difference between the two arises in whether a built-in function or method will call another object's overridden method instead of self.
PyPy will often be called without Cpython being called.
Two examples:
ex1:
class D(dict):
def __getitem__(self, key):
return "%r from D" % (key,)
class A(object):
pass
a = A()
a.__dict__ = D()
a.foo = "a's own foo"
print a.foo
# CPython => a's own foo
# PyPy => 'foo' from D
ex2:
glob = D(foo="base item")
loc = {}
exec "print foo" in glob, loc
# CPython => base item
# PyPy => 'foo' from D
Therefore, in the implementation structure of CPython, most of the built-in methods will ignore the overridden method, so UserDict, UserString, and UserList are generated to solve this problem.
In : class NewDict(dict):
...: def __getitem__(self, key):
...: return 42
...:
In : d = NewDict(a=1)
In : d
Out: {'a': 42}
In : d2 = {}
In : d2.update(d) #CPython中的update会忽略NewDict中的__getitem__方法
In : d2
Out: {'a': 1}