Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit883a803

Browse files
committed
dcos: add detailed README for Section 22 - Multiple Inheritance
🧬 Learn how to build classes that inherit from multiple parent classes in Python:- 🔄 Understand how Python resolves method calls using MRO (Method Resolution Order)- 🧭 Use `super()` effectively in a multiple inheritance context- 🧩 Introduce mixin classes for reusable cross-cutting functionality- 📦 Real-world example – implementing a `Contact` class with multiple behaviors (Email, SMS, Phone)- 💡 Hidden notes: - Avoid the "diamond problem" by designing clean hierarchies - Use mixins to share logic without deep inheritance chains - Always check MRO with `ClassName.__mro__` or `help(ClassName)` - Prefer composition over complex inheritance when possible
1 parent546200e commit883a803

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
#🧬 Section 22: Multiple Inheritance
2+
##Understanding and Using Multiple Inheritance in Python
3+
4+
🔁**Learn how to create classes that inherit from multiple parent classes** — a powerful but sometimes confusing feature of Python’s object-oriented programming.
5+
6+
This section covers:
7+
- 🧱 What is multiple inheritance?
8+
- 🧭 How Python resolves method calls using MRO (Method Resolution Order)
9+
- 🔄 The use of`super()` in multiple inheritance
10+
- 🧩 Mixin classes for reusable behavior
11+
- 💡 Hidden tips, best practices, and common pitfalls
12+
13+
14+
15+
##🧠 What You'll Learn
16+
17+
| Concept| Description|
18+
|--------|-------------|
19+
|**Multiple Inheritance**| A class inherits from more than one base class|
20+
|**MRO – Method Resolution Order**| Determines the order in which methods are resolved|
21+
|**`super()`**| Calls the next class in the MRO, often used in constructors|
22+
|**Mixins**| Classes that provide reusable functionality without being full base classes|
23+
|**Diamond Problem**| When two parent classes share a common ancestor|
24+
|**Avoiding Tight Coupling**| Design clean hierarchies without breaking encapsulation|
25+
26+
27+
28+
##🧱 Introduction to Multiple Inheritance
29+
30+
In Python, a class can inherit from multiple parent classes. This allows you to combine behaviors from different sources into a single class.
31+
32+
🔹**Basic Syntax:**
33+
```python
34+
classChildClass(Parent1,Parent2,Parent3):
35+
pass
36+
```
37+
38+
🔹**Example – Flying Car**
39+
```python
40+
classCar:
41+
defstart(self):
42+
print("Starting Car")
43+
44+
classFlyable:
45+
deffly(self):
46+
print("Flying Mode Activated")
47+
48+
classFlyingCar(Car,Flyable):
49+
pass
50+
```
51+
52+
🔸**Usage:**
53+
```python
54+
flying_car= FlyingCar()
55+
flying_car.start()# From Car
56+
flying_car.fly()# From Flyable
57+
```
58+
59+
---
60+
61+
##🧭 Method Resolution Order (MRO)
62+
63+
Python uses a depth-first, left-to-right algorithm called**MRO** to determine which method to call when multiple parents define the same method.
64+
65+
🔹**Check MRO:**
66+
```python
67+
print(FlyingCar.__mro__)
68+
# Output: (<class 'FlyingCar'>, <class 'Car'>, <class 'Flyable'>, <class 'object'>)
69+
```
70+
71+
🔸 Or use:
72+
```python
73+
help(FlyingCar)# Shows full MRO tree
74+
```
75+
76+
77+
78+
##🔁 Using`super()` with Multiple Inheritance
79+
80+
Use`super()` carefully in multiple inheritance to ensure all parent`__init__` methods are called correctly.
81+
82+
🔹**Example – Proper Initialization**
83+
```python
84+
classVehicle:
85+
def__init__(self):
86+
print("Initializing Vehicle")
87+
88+
classCar(Vehicle):
89+
def__init__(self):
90+
super().__init__()
91+
print("Initializing Car")
92+
93+
classFlyable(Vehicle):
94+
def__init__(self):
95+
super().__init__()
96+
print("Initializing Flyable")
97+
98+
classFlyingCar(Car,Flyable):
99+
def__init__(self):
100+
super().__init__()
101+
print("Finalizing FlyingCar")
102+
```
103+
104+
🔸**Usage:**
105+
```python
106+
car= FlyingCar()
107+
# Output:
108+
# Initializing Vehicle
109+
# Initializing Flyable
110+
# Initializing Car
111+
# Finalizing FlyingCar
112+
```
113+
114+
📌 This works because of**C3 linearization**, Python's MRO algorithm.
115+
116+
117+
##🧩 Real-World Example – Employee with Skills and Dependents
118+
119+
Let’s build a system where an`Employee` class inherits from both`Person` and a mixin class that adds JSON serialization support.
120+
121+
###🧱 Base Class – Person
122+
```python
123+
classPerson:
124+
def__init__(self,name):
125+
self.name= name
126+
print(f"{self.name} initialized")
127+
```
128+
129+
###🧩 Mixin – JSON Support
130+
```python
131+
classJsonSerializableMixin:
132+
defto_json(self):
133+
import json
134+
return json.dumps(self.__dict__)
135+
```
136+
137+
###🧬 Combining Both – Employee
138+
```python
139+
classEmployee(Person,JsonSerializableMixin):
140+
def__init__(self,name,role,salary):
141+
super().__init__(name)
142+
self.role= role
143+
self.salary= salary
144+
```
145+
146+
🔸**Usage:**
147+
```python
148+
emp= Employee("Alice","Developer",90000)
149+
print(emp.to_json())# {"name": "Alice", "role": "Developer", "salary": 90000}
150+
```
151+
152+
153+
154+
##🧰 Introducing Mixin Classes
155+
156+
A**mixin** is a class that provides methods to other classes through inheritance but is not meant to be instantiated on its own.
157+
158+
🔹**Example – Logging Mixin**
159+
```python
160+
classLoggable:
161+
deflog(self,message):
162+
print(f"[{self.__class__.__name__}]{message}")
163+
```
164+
165+
🔹**Using Mixin in a Class**
166+
```python
167+
classUser(Person,Loggable):
168+
def__init__(self,name):
169+
super().__init__(name)
170+
171+
user= User("Bob")
172+
user.log("Logged in")# [User] Logged in
173+
```
174+
175+
🔸 Mixins help reduce code duplication by grouping reusable logic like logging, caching, or validation.
176+
177+
178+
179+
##🧨 Avoiding the Diamond Problem
180+
181+
The**diamond problem** occurs when a child class inherits from two classes that both inherit from the same parent.
182+
183+
🔹**Classic Diamond Problem:**
184+
```python
185+
classA:
186+
defgreet(self):
187+
print("Hello from A")
188+
189+
classB(A):
190+
defgreet(self):
191+
print("Hello from B")
192+
193+
classC(A):
194+
defgreet(self):
195+
print("Hello from C")
196+
197+
classD(B,C):
198+
pass
199+
```
200+
201+
🔸 Now calling`D().greet()` will run`B.greet()` since it comes first in MRO.
202+
203+
🔹**Why? Because of C3 Linearization:**
204+
```python
205+
print(D.__mro__)
206+
# D -> B -> C -> A -> object
207+
```
208+
209+
🔸 This ensures only one path is followed — avoiding ambiguity.
210+
211+
212+
##🧪 Real-World Use Case – Payment Gateway System
213+
214+
Let’s create a system where a payment processor can support multiple interfaces.
215+
216+
###🧱 Base Classes
217+
```python
218+
classPaymentProcessor:
219+
defprocess_payment(self,amount):
220+
raiseNotImplementedError()
221+
222+
classRefundProcessor:
223+
defprocess_refund(self,amount):
224+
raiseNotImplementedError()
225+
```
226+
227+
###🧩 Mixins
228+
```python
229+
classLoggingMixin:
230+
deflog(self,message):
231+
print(f"[LOG]{message}")
232+
233+
classAuditMixin:
234+
defaudit(self,action):
235+
print(f"Audit:{action}")
236+
```
237+
238+
###🧬 Combined Processor
239+
```python
240+
classHybridPaymentProcessor(PaymentProcessor,RefundProcessor,LoggingMixin,AuditMixin):
241+
defprocess_payment(self,amount):
242+
self.log(f"Processing payment of ${amount}")
243+
self.audit("payment_processed")
244+
print(f"Paid ${amount}")
245+
246+
defprocess_refund(self,amount):
247+
self.log(f"Processing refund of ${amount}")
248+
self.audit("refund_processed")
249+
print(f"Refunded ${amount}")
250+
```
251+
252+
🔸**Usage:**
253+
```python
254+
processor= HybridPaymentProcessor()
255+
processor.process_payment(100)
256+
# Output:
257+
# [LOG] Processing payment of $100
258+
# Audit: payment_processed
259+
# Paid $100
260+
```
261+
262+
263+
264+
##💡 Hidden Tips & Notes
265+
266+
- 🧩 Use`__mro__` or`help(Class)` to inspect method resolution order.
267+
- 🧱 Always call`super().__init__()` in parent classes to ensure proper initialization.
268+
- 📦 Prefer shallow inheritance trees — deep ones become hard to maintain.
269+
- 🧵 Mixins should have clear names like`JsonSerializable`,`Loggable`,`CacheMixin`.
270+
- 🧾 Mixins shouldn’t have their own state unless necessary — keep them lightweight.
271+
- 🚫 Don't overuse multiple inheritance — prefer composition (`has-a`) over inheritance (`is-a`) when possible.
272+
- 🧠 Understand the**C3 linearization algorithm** used by Python for MRO.
273+
274+
275+
##📌 Summary
276+
277+
| Feature| Purpose|
278+
|--------|---------|
279+
|**Multiple Inheritance**| Combine features from multiple parent classes|
280+
|**MRO (Method Resolution Order)**| Define which method gets called in case of conflict|
281+
|**`super()`**| Call parent logic safely across multiple paths|
282+
|**Mixins**| Add reusable behavior without deep hierarchies|
283+
|**Diamond Problem**| Occurs when two classes share a common ancestor|
284+
|**Best Practice**| Keep inheritance chains shallow and meaningful|
285+
286+
287+
🎉 Congratulations! You now understand how to effectively use**multiple inheritance in Python**, including how to resolve conflicts with MRO and how to write modular, reusable mixins.
288+
289+
Next up: 🧰**Section 23: Descriptors** – learn how to manage attribute access at a deeper level using descriptors.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp