Inheritance: For Good or For Worse

1. Subclassing Built-In Types Is Tricky

Since Python 2.2, subclassing built-in types such as list or dict can be done but there is a major caveat: the code of the built-ins (written in C) does not call special methods overridden by user-defined classes.

A good short description of the problem is in the documentation for PyPy, shown as below:

Officially, CPython has no rule at all for when exactly overridden method of subclasses of built-in types get implicitly called or not. As an approximation, these methods are never called by other built-in methods of the same object. For example, an overridden __getitem__() in a subclass of dict will not be called e.g. the built-in get() method.

Example 12-1. Our __setitem__ override is ignored by the __init__ and __update__ methods of the built-in dict.

>>> class DoppelDict(dict):
...     def __setitem__(self, key, value):
...         super().__setitem__(key, [value] * 2)
...
>>> dd = DoppelDict(one=1)      # The __init__ method inherited from dict clearly ignored that __setitem__ was overridden: the value of 'one' is not duplicated.
>>> dd
{'one': 1}
>>> dd['two'] = 2   # The [] operator calls our __setitem__ and works as expected: 'two' maps to the duplicated value [2, 2]
>>> dd
{'one': 1, 'two': [2, 2]}
>>> dd.update(three=3)      # The update method from dict does not use our version of __setitem__ either: the value of 'three' was not duplicated.
>>> dd
{'one': 1, 'two': [2, 2], 'three': 3}

Example 12-2. The __getitem__ of AnswerDict is bypassed by dict.update

>>> class AnswerDict(dict):
...     def __getitem__(self, key):
...         return 42
... 
>>> ad = AnswerDict(a='foo')
>>> ad
{'a': 'foo'}
>>> ad['a']     # ad['a'] returns 42, as expected.
42
>>> d = {}
>>> d.update(ad)
>>> d['a']      # The dict.update method ignored our AnswerDict.__getitem__
'foo'
>>> d
{'a': 'foo'}


"""
Subclassing built-in types like dict or list or str directly is error-prone because the built-in methods mostly ignore 
user-defined override. Instead of subclassing the built-ins, derive your classes from the collections module using
UserDict, UserList, and UserString, which are designed to be easily extended.
"""

end...

猜你喜欢

转载自www.cnblogs.com/neozheng/p/12359845.html