-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathitem_25.py
127 lines (92 loc) · 3.28 KB
/
item_25.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
class MyBaseClass(object):
def __init__(self, value):
self.value = value
class MyChildClass(MyBaseClass):
def __init__(self):
MyBaseClass.__init__(self, 5)
class TimesTwo(object):
def __init__(self):
self.value *=2
class PlusFive(object):
def __init__(self):
self.value +=5
class OneWay(MyBaseClass, TimesTwo, PlusFive):
def __init__(self, value):
MyBaseClass.__init__(self, value)
TimesTwo.__init__(self)
PlusFive.__init__(self)
class AnotherWay(MyBaseClass, PlusFive, TimesTwo):
def __init__(self, value):
MyBaseClass.__init__(self, value)
TimesTwo.__init__(self)
PlusFive.__init__(self)
class TimesFive(MyBaseClass):
def __init__(self, value):
MyBaseClass.__init__(self, value)
self.value *=5
class PlusTwo(MyBaseClass):
def __init__(self, value):
MyBaseClass.__init__(self, value)
self.value +=2
class ThisWay(TimesFive, PlusTwo):
""" Demonstrates a Diamond inheritance.
This is when a subclass inherits from two separate classes,
that have the same superclass somewhere in the hierarchy.
"""
def __init__(self, value):
TimesFive.__init__(self,value)
PlusTwo.__init__(self, value)
class TimesFiveCorrect(MyBaseClass):
"""
- Python 2.2 added the 'super' built in method and defined the MRO
MRO Method Resolution Order
- MRO standardizes which superclasses are initialized before others
depth-first, left-to-right
- Here we use the Python2 style call to super
"""
def __init__(self, value):
super(TimesFiveCorrect, self).__init__(value)
self.value *=5
class PlusTwoCorrect(MyBaseClass):
def __init__(self, value):
super(PlusTwoCorrect, self).__init__(value)
self.value +=2
class GoodWay(TimesFiveCorrect, PlusTwoCorrect):
"""
- The order seems backwards... shouldn't TimesFiveCorrect.__init__ have run first?
Inspecting the MRO for this class, we find the answer
>>> from pprint import pprint
>>> pprint(GoodWay.mro())
[<class '__main__.GoodWay'>,
<class '__main__.TimesFiveCorrect'>,
<class '__main__.PlusTwoCorrect'>,
<class '__main__.MyBaseClass'>,
<class 'object'>]
- Calling GoodWay(5)
it calls TimesFiveCorrect.__init__ which calls PlusTwoCorrect.__init__
which calls MyBaseClass.__init__
- Once this reaches the top of the diamond, then all the inits do their
work in the opposite order from how their __init__ functions were called
bottom up.
"""
def __init__(self, value):
super(GoodWay, self).__init__(value)
class Explicit(MyBaseClass):
def __init__(self, value):
super(__class__, self).__init__(value *2)
class Implicit(MyBaseClass):
"""Python3 style to call super"""
def __init__(self, value):
super().__init__(value * 2)
def main():
# foo = OneWay(5)
# print('First ordering is (5 *2) + 5 =', foo.value)
# bar = AnotherWay(5)
# print('Second ordering is still ', bar.value)
# foo = ThisWay(5)
# print('Should be (5 * 5) + 2 = 27 but is', foo.value)
foo = GoodWay(5)
print('Should be 5 * (5 + 2) = 35 and is', foo.value)
assert Explicit(10).value == Implicit(10).value
if __name__ == '__main__':
main()