Chapter 12: Inheritance advantages and disadvantages
12.1 subclass built-in types a lot of trouble
Before Python2.2, built-in types (such as list or dict) can not subclass. After Python2.2, built-in types can be subclassed, but there are important considerations: built-in types covered by the special class method is not called (written in C).
In [194]: class DoppelDict(dict): ...: def __setitem__(self, key, value): ...: super().__setitem__(key, [value] * 2) ...: In [195]: dd = DoppelDict(one=1) In [196]: dd Out[196]: {'one': 1} In [197]: dd['two'] = 2 In [198]: dd Out[198]: {'one': 1, 'two': [2, 2]} In [199]: dd.update(three=3) In [200]: dd Out[200]: {'one': 1, 'two': [2, 2], 'three': 3} In [201]:
Through the code book, the effect can be seen only when defined __setitem__ assignment produced, additional initialization, no dictionary update __setitem__ using a modified method, using the original method of the superclass.
__missing__ method was able to work as expected in this terrible situation, although this is just a special case.
If other class built-in methods of the class method calls, if covered, it will not be called.
In [202]: class AnswerDict(dict): ...: def __getitem__(self, key): ...: return 42 ...: In [203]: ad = AnswerDict(a='foo') In [204]: ad['a'] Out[204]: 42 In [205]: d = {} In [206]: d.update(ad) In [207]: d['a'] Out[207]: 'foo' In [208]: d Out[208]: {'a': 'foo'} In [209]:
This should be more intuitive, because you're only in your own class which defines __getitem__, all methods in addition object to call you (upgrade here), and will not use you to modify, or use the parent class when the list.
Built-in types directly subclassing (e.g. dict, str, list), since the built-in type of method usually ignored method covered by a user. Do not subclass built-in types,
It should be a subclass of these three modules
In [211]: collections.UserDict
Out[211]: collections.UserDict
In [212]: collections.UserList
Out[212]: collections.UserList
In [213]: collections.UserString
Out[213]: collections.UserString
In [219]: import collections ...: ...: class DoppelDict2(collections.UserDict): ...: ...: def __setitem__(self, key, value): ...: return super(DoppelDict2, self).__setitem__(key, [value] *2) ...: ...: def __getitem__(self, item): ...: ...: return self.data[item] * 2 ...: In [220]: In [220]: dd = DoppelDict2(one=1) In [221]: dd Out[221]: {'one': [1, 1]} In [222]: dd['one'] Out[222]: [1, 1, 1, 1] In [223]: dd.get('one') Out[223]: [1, 1, 1, 1] In [224]: dd.update(three=3) In [225]: dd Out[225]: {'one': [1, 1], 'three': [3, 3]} In [226]:
As mentioned above, __getitem__ attribute data dictionary in self.data inside, I add.
In [226]: class AnswerDict2(UserDict): ...: def __getitem__(self, key): ...: return 42 ...: ...: In [227]: ad = AnswerDict2(a='foo') In [228]: ad['a'] Out[228]: 42 In [229]: ad Out[229]: {'a': 'foo'} In [230]: d = dict() In [231]: d.update(ad) In [232]: d Out[232]: {'a': 42} In [233]: d['a'] Out[233]: 42
Can be found through this and other objects when calling the update, the ad calls __getitem__ method, due to the inherited UserDict, all with the revised methodology.
12.2 multiple inheritance and method resolution order.
class A(object): def ping(self): print('ping', self) class B(A): def pong(self): print('pong', self) class C(A): def pong(self): print('PONG', self) class D(B, C): def ping(self): super(D, self).ping() print('post-ping', self) def pingpong(self): self.ping() super().ping() self.pong() super().pong() C.pong(self)
In [254]: d = D() In [255]: d.pong() pong <__main__.D object at 0x10e0a4cd0> In [256]: C.pong(d) PONG <__main__.D object at 0x10e0a4cd0> In [257]: D.__mro__ Out[257]: (__main__.D, __main__.B, __main__.C, __main__.A, object) In [258]:
The above is performed in two ways, one is performed by the instance of the parent class pong, executed in the order of __mro__.
There is also a property directly through the class perform, display execution, rape this little feeling.
General delegate the implementation of the parent class, use super () is better.
In [259]: d.ping() ping <__main__.D object at 0x10e0a4cd0> post-ping <__main__.D object at 0x10e0a4cd0>
A first output line, based on a layer __mro__ looking directly to class A is performed inside this property.
...: def pingpong(self): ...: self.ping() ...: super().ping() ...: self.pong() ...: super().pong() ...: C.pong(self)
result
d.pingpong() ping <__main__.D object at 0x10e0a4cd0> post-ping <__main__.D object at 0x10e0a4cd0> ping <__main__.D object at 0x10e0a4cd0> pong <__main__.D object at 0x10e0a4cd0> pong <__main__.D object at 0x10e0a4cd0> PONG <__main__.D object at 0x10e0a4cd0>
Finally, a method of execution.
Prime Minister execution self.ping (), that they have this property, after performing self.ping () output
Two execution
The first ping <__ main __. D object at 0x10e0a4cd0>, is performed to the ping parent class's parent class A,
The second post-ping <__ main __. D object at 0x10e0a4cd0> execution, inside their own method.
Next super.ping (), ping is performed a parent class of the parent class A
self.pong and Super (). pong result will be identical, since there is no self pong property itself, the need to look for the parent class of the property by sequentially __mro__.
super (). pong is through __mro__ to find the parent class property.
Finally, a parent attribute that is running through explicit manner.
A code book back, demonstrate some of the several classes __mro__
In [269]: bool.__mro__ Out[269]: (bool, int, object) In [270]: import numbers In [271]: numbers.Integral.__mro__ Out[271]: (numbers.Integral, numbers.Rational, numbers.Real, numbers.Complex, numbers.Number, object) In [272]: import io In [273]: io.BytesIO.__mro__ Out[273]: (_io.BytesIO, _io._BufferedIOBase, _io._IOBase, object) In [274]: io.TextIOWrapper.__mro__ Out[274]: (_io.TextIOWrapper, _io._TextIOBase, _io._IOBase, object) In [275]:
The back of the book describes the inheritance and Django using Tkinter classes in view of my limited ability, practical operation of two modules basically nothing, so I can not tell a lot of the book to understand.
We can only look back.