OOP Advanced
Mixins
Composable Behavior
You have 10 classes that need JSON serialization. Instead of copying code to
each, create a JsonMixin with to_json() method. Any class can mix it in
to gain that capability - composition over inheritance.
Basic mixin
A small class that adds one capability.
# Mixin Basics
def main():
print("=== Mixin Basics ===\n")
# What is a mixin?
print("--- What is a Mixin? ---")
print("A small class that provides specific functionality")
print("to be 'mixed into' other classes.\n")
# Simple mixin example
print("--- Simple Mixin Example ---")
# Product with RepresentationMixin
product = Product("Laptop", 999.99)
print(f"Product info: {product.get_info()}")
print(f"Repr: {product!r}")
# Order with RepresentationMixin
order = Order("ORD-001", 5)
print(f"Order info: {order.get_info()}")
print(f"Repr: {order!r}")
# Mixin adds functionality to different classes
print("\n--- Same Mixin, Different Classes ---")
# Cat with VoiceMixin
cat = Cat("Whiskers")
print(f"{cat.name}: ", end="")
cat.speak()
cat.whisper()
# Dog with VoiceMixin
dog = Dog("Buddy")
print(f"{dog.name}: ", end="")
dog.speak()
dog.whisper()
# Mixin naming convention
print("\n--- Naming Convention ---")
print("Mixins typically end with 'Mixin':")
print(" • LoggingMixin")
print(" • SerializableMixin")
print(" • ComparableMixin")
print(" • RepresentationMixin")
print("\n=== Key Points ===")
print("""
1. Mixins add specific functionality
2. Usually don't have __init__ (or minimal)
3. Designed to be combined with other classes
4. Name ends with 'Mixin' by convention
5. Focus on ONE responsibility per mixin
""")
# RepresentationMixin - adds string representations
class RepresentationMixin:
"""Mixin that provides string representation methods."""
def get_info(self):
"""Return formatted info string."""
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
"""Return debug representation."""
return self.get_info()
# VoiceMixin - adds voice capabilities
class VoiceMixin:
"""Mixin that provides voice-related methods."""
sound = "..."
def speak(self):
"""Make the sound loudly."""
print(f"{self.sound}!")
def whisper(self):
"""Make the sound quietly."""
print(f"({self.sound.lower()})")
# Classes using RepresentationMixin
class Product(RepresentationMixin):
"""Product class with representation mixin."""
def __init__(self, name: str, price: float):
self.name = name
self.price = price
class Order(RepresentationMixin):
"""Order class with representation mixin."""
def __init__(self, order_id: str, quantity: int):
self.order_id = order_id
self.quantity = quantity
# Classes using VoiceMixin
class Cat(VoiceMixin):
"""Cat class with voice mixin."""
sound = "Meow"
def __init__(self, name: str):
self.name = name
class Dog(VoiceMixin):
"""Dog class with voice mixin."""
sound = "Woof"
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
# Mixin Basics
def main():
print("=== Mixin Basics ===\n")
# What is a mixin?
print("--- What is a Mixin? ---")
print("A small class that provides specific functionality")
print("to be 'mixed into' other classes.\n")
# Simple mixin example
print("--- Simple Mixin Example ---")
# Product with RepresentationMixin
product = Product("Tablet", 349.99)
print(f"Product info: {product.get_info()}")
print(f"Repr: {product!r}")
# Order with RepresentationMixin
order = Order("ORD-001", 5)
print(f"Order info: {order.get_info()}")
print(f"Repr: {order!r}")
# Mixin adds functionality to different classes
print("\n--- Same Mixin, Different Classes ---")
# Cat with VoiceMixin
cat = Cat("Whiskers")
print(f"{cat.name}: ", end="")
cat.speak()
cat.whisper()
# Dog with VoiceMixin
dog = Dog("Buddy")
print(f"{dog.name}: ", end="")
dog.speak()
dog.whisper()
# Mixin naming convention
print("\n--- Naming Convention ---")
print("Mixins typically end with 'Mixin':")
print(" • LoggingMixin")
print(" • SerializableMixin")
print(" • ComparableMixin")
print(" • RepresentationMixin")
print("\n=== Key Points ===")
print("""
1. Mixins add specific functionality
2. Usually don't have __init__ (or minimal)
3. Designed to be combined with other classes
4. Name ends with 'Mixin' by convention
5. Focus on ONE responsibility per mixin
""")
# RepresentationMixin - adds string representations
class RepresentationMixin:
"""Mixin that provides string representation methods."""
def get_info(self):
"""Return formatted info string."""
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
"""Return debug representation."""
return self.get_info()
# VoiceMixin - adds voice capabilities
class VoiceMixin:
"""Mixin that provides voice-related methods."""
sound = "..."
def speak(self):
"""Make the sound loudly."""
print(f"{self.sound}!")
def whisper(self):
"""Make the sound quietly."""
print(f"({self.sound.lower()})")
# Classes using RepresentationMixin
class Product(RepresentationMixin):
"""Product class with representation mixin."""
def __init__(self, name: str, price: float):
self.name = name
self.price = price
class Order(RepresentationMixin):
"""Order class with representation mixin."""
def __init__(self, order_id: str, quantity: int):
self.order_id = order_id
self.quantity = quantity
# Classes using VoiceMixin
class Cat(VoiceMixin):
"""Cat class with voice mixin."""
sound = "Meow"
def __init__(self, name: str):
self.name = name
class Dog(VoiceMixin):
"""Dog class with voice mixin."""
sound = "Woof"
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
# Mixin Basics
def main():
print("=== Mixin Basics ===\n")
# What is a mixin?
print("--- What is a Mixin? ---")
print("A small class that provides specific functionality")
print("to be 'mixed into' other classes.\n")
# Simple mixin example
print("--- Simple Mixin Example ---")
# Product with RepresentationMixin
product = Product("Monitor", 229.99)
print(f"Product info: {product.get_info()}")
print(f"Repr: {product!r}")
# Order with RepresentationMixin
order = Order("ORD-001", 5)
print(f"Order info: {order.get_info()}")
print(f"Repr: {order!r}")
# Mixin adds functionality to different classes
print("\n--- Same Mixin, Different Classes ---")
# Cat with VoiceMixin
cat = Cat("Whiskers")
print(f"{cat.name}: ", end="")
cat.speak()
cat.whisper()
# Dog with VoiceMixin
dog = Dog("Buddy")
print(f"{dog.name}: ", end="")
dog.speak()
dog.whisper()
# Mixin naming convention
print("\n--- Naming Convention ---")
print("Mixins typically end with 'Mixin':")
print(" • LoggingMixin")
print(" • SerializableMixin")
print(" • ComparableMixin")
print(" • RepresentationMixin")
print("\n=== Key Points ===")
print("""
1. Mixins add specific functionality
2. Usually don't have __init__ (or minimal)
3. Designed to be combined with other classes
4. Name ends with 'Mixin' by convention
5. Focus on ONE responsibility per mixin
""")
# RepresentationMixin - adds string representations
class RepresentationMixin:
"""Mixin that provides string representation methods."""
def get_info(self):
"""Return formatted info string."""
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
"""Return debug representation."""
return self.get_info()
# VoiceMixin - adds voice capabilities
class VoiceMixin:
"""Mixin that provides voice-related methods."""
sound = "..."
def speak(self):
"""Make the sound loudly."""
print(f"{self.sound}!")
def whisper(self):
"""Make the sound quietly."""
print(f"({self.sound.lower()})")
# Classes using RepresentationMixin
class Product(RepresentationMixin):
"""Product class with representation mixin."""
def __init__(self, name: str, price: float):
self.name = name
self.price = price
class Order(RepresentationMixin):
"""Order class with representation mixin."""
def __init__(self, order_id: str, quantity: int):
self.order_id = order_id
self.quantity = quantity
# Classes using VoiceMixin
class Cat(VoiceMixin):
"""Cat class with voice mixin."""
sound = "Meow"
def __init__(self, name: str):
self.name = name
class Dog(VoiceMixin):
"""Dog class with voice mixin."""
sound = "Woof"
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
# Mixin Basics
def main():
print("=== Mixin Basics ===\n")
# What is a mixin?
print("--- What is a Mixin? ---")
print("A small class that provides specific functionality")
print("to be 'mixed into' other classes.\n")
# Simple mixin example
print("--- Simple Mixin Example ---")
# Product with RepresentationMixin
product = Product("Laptop", 999.99)
print(f"Product info: {product.get_info()}")
print(f"Repr: {product!r}")
# Order with RepresentationMixin
order = Order("ORD-001", 5)
print(f"Order info: {order.get_info()}")
print(f"Repr: {order!r}")
# Mixin adds functionality to different classes
print("\n--- Same Mixin, Different Classes ---")
# Cat with VoiceMixin
cat = Cat("Misty")
print(f"{cat.name}: ", end="")
cat.speak()
cat.whisper()
# Dog with VoiceMixin
dog = Dog("Buddy")
print(f"{dog.name}: ", end="")
dog.speak()
dog.whisper()
# Mixin naming convention
print("\n--- Naming Convention ---")
print("Mixins typically end with 'Mixin':")
print(" • LoggingMixin")
print(" • SerializableMixin")
print(" • ComparableMixin")
print(" • RepresentationMixin")
print("\n=== Key Points ===")
print("""
1. Mixins add specific functionality
2. Usually don't have __init__ (or minimal)
3. Designed to be combined with other classes
4. Name ends with 'Mixin' by convention
5. Focus on ONE responsibility per mixin
""")
# RepresentationMixin - adds string representations
class RepresentationMixin:
"""Mixin that provides string representation methods."""
def get_info(self):
"""Return formatted info string."""
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
"""Return debug representation."""
return self.get_info()
# VoiceMixin - adds voice capabilities
class VoiceMixin:
"""Mixin that provides voice-related methods."""
sound = "..."
def speak(self):
"""Make the sound loudly."""
print(f"{self.sound}!")
def whisper(self):
"""Make the sound quietly."""
print(f"({self.sound.lower()})")
# Classes using RepresentationMixin
class Product(RepresentationMixin):
"""Product class with representation mixin."""
def __init__(self, name: str, price: float):
self.name = name
self.price = price
class Order(RepresentationMixin):
"""Order class with representation mixin."""
def __init__(self, order_id: str, quantity: int):
self.order_id = order_id
self.quantity = quantity
# Classes using VoiceMixin
class Cat(VoiceMixin):
"""Cat class with voice mixin."""
sound = "Meow"
def __init__(self, name: str):
self.name = name
class Dog(VoiceMixin):
"""Dog class with voice mixin."""
sound = "Woof"
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
# Mixin Basics
def main():
print("=== Mixin Basics ===\n")
# What is a mixin?
print("--- What is a Mixin? ---")
print("A small class that provides specific functionality")
print("to be 'mixed into' other classes.\n")
# Simple mixin example
print("--- Simple Mixin Example ---")
# Product with RepresentationMixin
product = Product("Laptop", 999.99)
print(f"Product info: {product.get_info()}")
print(f"Repr: {product!r}")
# Order with RepresentationMixin
order = Order("ORD-001", 5)
print(f"Order info: {order.get_info()}")
print(f"Repr: {order!r}")
# Mixin adds functionality to different classes
print("\n--- Same Mixin, Different Classes ---")
# Cat with VoiceMixin
cat = Cat("Shadow")
print(f"{cat.name}: ", end="")
cat.speak()
cat.whisper()
# Dog with VoiceMixin
dog = Dog("Buddy")
print(f"{dog.name}: ", end="")
dog.speak()
dog.whisper()
# Mixin naming convention
print("\n--- Naming Convention ---")
print("Mixins typically end with 'Mixin':")
print(" • LoggingMixin")
print(" • SerializableMixin")
print(" • ComparableMixin")
print(" • RepresentationMixin")
print("\n=== Key Points ===")
print("""
1. Mixins add specific functionality
2. Usually don't have __init__ (or minimal)
3. Designed to be combined with other classes
4. Name ends with 'Mixin' by convention
5. Focus on ONE responsibility per mixin
""")
# RepresentationMixin - adds string representations
class RepresentationMixin:
"""Mixin that provides string representation methods."""
def get_info(self):
"""Return formatted info string."""
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
"""Return debug representation."""
return self.get_info()
# VoiceMixin - adds voice capabilities
class VoiceMixin:
"""Mixin that provides voice-related methods."""
sound = "..."
def speak(self):
"""Make the sound loudly."""
print(f"{self.sound}!")
def whisper(self):
"""Make the sound quietly."""
print(f"({self.sound.lower()})")
# Classes using RepresentationMixin
class Product(RepresentationMixin):
"""Product class with representation mixin."""
def __init__(self, name: str, price: float):
self.name = name
self.price = price
class Order(RepresentationMixin):
"""Order class with representation mixin."""
def __init__(self, order_id: str, quantity: int):
self.order_id = order_id
self.quantity = quantity
# Classes using VoiceMixin
class Cat(VoiceMixin):
"""Cat class with voice mixin."""
sound = "Meow"
def __init__(self, name: str):
self.name = name
class Dog(VoiceMixin):
"""Dog class with voice mixin."""
sound = "Woof"
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
sound ← (empty)
60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound→ (empty) = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.sound.lower()})") #?print_quiet868788# Classes using RepresentationMixin #?using_repr_mixin89class Product(RepresentationMixin): #?product_class90 """Product class with representation mixin."""9192 def __init__(self, name: str, price: float): #?product_init93 self.name = name #?product_name94 self.price = price #?product_price959697class Order(RepresentationMixin): #?order_class98 """Order class with representation mixin."""99100 def __init__(self, order_id: str, quantity: int): #?order_init101 self.order_id = order_id #?order_id102 self.quantity = quantity #?order_quantity103104105# Classes using VoiceMixin #?using_voice_mixin106class Cat(VoiceMixin): #?cat_class107 """Cat class with voice mixin."""108109 sound→ (empty) = "Meow" #?cat_sound110111 def __init__(self, name: str): #?cat_init112 self.name = name #?cat_name_attr113114115class Dog(VoiceMixin): #?dog_class116 """Dog class with voice mixin."""117118 sound→ (empty) = "Woof" #?dog_sounddef main():
3def main():4 print("=== Mixin Basics ===\n")56 # What is a mixin? #?what_mixin7 print("--- What is a Mixin? ---")8 print("A small class that provides specific functionality")9 print("to be 'mixed into' other classes.\n")1011 # Simple mixin example #?simple_mixin12 print("--- Simple Mixin Example ---")1314 # Product with RepresentationMixin #?product_demo15 product = Product("Laptop", 999.99) #?create_product16 #@product=Product("Tablet", 349.99), Product("Monitor", 229.99)output=== Mixin Basics === --- What is a Mixin? --- A small class that provides specific functionality to be 'mixed into' other classes. --- Simple Mixin Example ---self.name ← Laptop, self.price ← 999.99, product ← Product(name='Laptop', price=999.99)
14 # Product with RepresentationMixin #?product_demo15 product→ Product(name='Laptop', price=999.99) = Product("Laptop", 999.99) #?create_product16 #@product=Product("Tablet", 349.99), Product("Monitor", 229.99)17 print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}") #?print_product_info18 print(f"Repr: {product!r}") #?print_product_repr1920 # Order with RepresentationMixin #?order_demo21 order = Order("ORD-001", 5) #?create_order22 print(f"Order info: {order.get_info()}") #?print_order_info23 print(f"Repr: {order!r}") #?print_order_repr2425 # Mixin adds functionality to different classes #?different_classes26 print("\n--- Same Mixin, Different Classes ---")2728 # Cat with VoiceMixin #?cat_demo29 cat = Cat("Whiskers") #?create_cat30 #@cat=Cat("Misty"), Cat("Shadow")31 print(f"{cat.name}: ", end="") #?print_cat_name32 cat.speak() #?cat_speak33 cat.whisper() #?cat_whisper3435 # Dog with VoiceMixin #?dog_demo36 dog = Dog("Buddy") #?create_dog37 print(f"{dog.name}: ", end="") #?print_dog_name38 dog.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.sound.lower()})") #?print_quiet868788# Classes using RepresentationMixin #?using_repr_mixin89class Product(RepresentationMixin): #?product_class90 """Product class with representation mixin."""9192 def __init__(selfProduct(), nameLaptop: str, price999.99: float): #?product_init93 self.name→ Laptop = nameLaptop #?product_name94 self.price→ 999.99 = price999.99 #?product_priceattrs ← name='Laptop', price=999.99
pass 1 of 463def get_info(selfProduct(name='Laptop', price=999.99)): #?get_info_method64 """Return formatted info string."""65 attrs→ name='Laptop', price=999.99 = ", ".join(f"{k(empty)}={v(empty)!r}" for k, v in self.__dict__{'name': 'Laptop', 'price': 999.99}.items()) #?format_attrs66 return f"{self.__class__.__name__Product}({attrsname='Laptop', price=999.99})" #?return_infoAll 4 passes — pass 1 is the card above pass selfself.__dict__self.__class__.__name__attrs1 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 2 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 3 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 4 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 print(f"Product info: {product.get_info()}") #?print_product_info
16#@product=Product("Tablet", 349.99), Product("Monitor", 229.99)17print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}") #?print_product_info18print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}") #?print_product_reproutputProduct info: Product(name='Laptop', price=999.99)print(f"Repr: {product!r}") #?print_product_repr
17print(f"Product info: {product.get_info()}") #?print_product_info18print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}") #?print_product_repr1920# Order with RepresentationMixin #?order_demo21order = Order("ORD-001", 5) #?create_order22print(f"Order info: {order.get_info()}") #?print_order_infooutputRepr: Product(name='Laptop', price=999.99)self.order_id ← ORD-001, self.quantity ← 5, order ← Order(order_id='ORD-001', quantity=5)
20 # Order with RepresentationMixin #?order_demo21 order→ Order(order_id='ORD-001', quantity=5) = Order("ORD-001", 5) #?create_order22 print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}") #?print_order_info23 print(f"Repr: {order!r}") #?print_order_repr2425 # Mixin adds functionality to different classes #?different_classes26 print("\n--- Same Mixin, Different Classes ---")2728 # Cat with VoiceMixin #?cat_demo29 cat = Cat("Whiskers") #?create_cat30 #@cat=Cat("Misty"), Cat("Shadow")31 print(f"{cat.name}: ", end="") #?print_cat_name32 cat.speak() #?cat_speak33 cat.whisper() #?cat_whisper3435 # Dog with VoiceMixin #?dog_demo36 dog = Dog("Buddy") #?create_dog37 print(f"{dog.name}: ", end="") #?print_dog_name38 dog.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.sound.lower()})") #?print_quiet868788# Classes using RepresentationMixin #?using_repr_mixin89class Product(RepresentationMixin): #?product_class90 """Product class with representation mixin."""9192 def __init__(self, name: str, price: float): #?product_init93 self.name = name #?product_name94 self.price = price #?product_price959697class Order(RepresentationMixin): #?order_class98 """Order class with representation mixin."""99100 def __init__(selfOrder(), order_idORD-001: str, quantity5: int): #?order_init101 self.order_id→ ORD-001 = order_idORD-001 #?order_id102 self.quantity→ 5 = quantity5 #?order_quantityprint(f"Order info: {order.get_info()}") #?print_order_info
21order = Order("ORD-001", 5) #?create_order22print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}") #?print_order_info23print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}") #?print_order_reproutputOrder info: Order(order_id='ORD-001', quantity=5)print(f"Repr: {order!r}") #?print_order_repr
22print(f"Order info: {order.get_info()}") #?print_order_info23print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}") #?print_order_repr2425# Mixin adds functionality to different classes #?different_classes26print("\n--- Same Mixin, Different Classes ---")2728# Cat with VoiceMixin #?cat_demo29cat = Cat("Whiskers") #?create_cat30#@cat=Cat("Misty"), Cat("Shadow")outputRepr: Order(order_id='ORD-001', quantity=5) --- Same Mixin, Different Classes ---self.name ← Whiskers, cat ← ⟨Cat A⟩
28 # Cat with VoiceMixin #?cat_demo29 cat→ ⟨Cat A⟩ = Cat("Whiskers") #?create_cat30 #@cat=Cat("Misty"), Cat("Shadow")31 print(f"{cat.nameWhiskers}: ", end="") #?print_cat_name32 cat⟨Cat A⟩.speak() #?cat_speak33 cat.whisper() #?cat_whisper3435 # Dog with VoiceMixin #?dog_demo36 dog = Dog("Buddy") #?create_dog37 print(f"{dog.name}: ", end="") #?print_dog_name38 dog.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.sound.lower()})") #?print_quiet868788# Classes using RepresentationMixin #?using_repr_mixin89class Product(RepresentationMixin): #?product_class90 """Product class with representation mixin."""9192 def __init__(self, name: str, price: float): #?product_init93 self.name = name #?product_name94 self.price = price #?product_price959697class Order(RepresentationMixin): #?order_class98 """Order class with representation mixin."""99100 def __init__(self, order_id: str, quantity: int): #?order_init101 self.order_id = order_id #?order_id102 self.quantity = quantity #?order_quantity103104105# Classes using VoiceMixin #?using_voice_mixin106class Cat(VoiceMixin): #?cat_class107 """Cat class with voice mixin."""108109 sound = "Meow" #?cat_sound110111 def __init__(self⟨Cat A⟩, nameWhiskers: str): #?cat_init112 self.name→ Whiskers = nameWhiskers #?cat_name_attroutputWhiskers:def speak(self): #?speak_method
pass 1 of 231 print(f"{cat.name}: ", end="") #?print_cat_name32 cat⟨Cat A⟩.speak() #?cat_speak33 cat⟨Cat A⟩.whisper() #?cat_whisper3435 # Dog with VoiceMixin #?dog_demo36 dog = Dog("Buddy") #?create_dog37 print(f"{dog.name}: ", end="") #?print_dog_name38 dog.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self⟨Cat A⟩): #?speak_method80 """Make the sound loudly."""81 print(f"{self.soundMeow}!") #?print_loudoutputMeow!def whisper(self): #?whisper_method
pass 1 of 232 cat.speak() #?cat_speak33 cat⟨Cat A⟩.whisper() #?cat_whisper3435 # Dog with VoiceMixin #?dog_demo36 dog = Dog("Buddy") #?create_dog37 print(f"{dog.name}: ", end="") #?print_dog_name38 dog.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self⟨Cat A⟩): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.soundMeow.lower()})") #?print_quietoutput(meow)self.name ← Buddy, dog ← ⟨Dog B⟩
35 # Dog with VoiceMixin #?dog_demo36 dog→ ⟨Dog B⟩ = Dog("Buddy") #?create_dog37 print(f"{dog.nameBuddy}: ", end="") #?print_dog_name38 dog⟨Dog B⟩.speak() #?dog_speak39 dog.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.sound.lower()})") #?print_quiet868788# Classes using RepresentationMixin #?using_repr_mixin89class Product(RepresentationMixin): #?product_class90 """Product class with representation mixin."""9192 def __init__(self, name: str, price: float): #?product_init93 self.name = name #?product_name94 self.price = price #?product_price959697class Order(RepresentationMixin): #?order_class98 """Order class with representation mixin."""99100 def __init__(self, order_id: str, quantity: int): #?order_init101 self.order_id = order_id #?order_id102 self.quantity = quantity #?order_quantity103104105# Classes using VoiceMixin #?using_voice_mixin106class Cat(VoiceMixin): #?cat_class107 """Cat class with voice mixin."""108109 sound = "Meow" #?cat_sound110111 def __init__(self, name: str): #?cat_init112 self.name = name #?cat_name_attr113114115class Dog(VoiceMixin): #?dog_class116 """Dog class with voice mixin."""117118 sound = "Woof" #?dog_sound119120 def __init__(self⟨Dog B⟩, nameBuddy: str): #?dog_init121 self.name→ Buddy = nameBuddy #?dog_name_attroutputBuddy:def speak(self): #?speak_method
pass 2 of 237 print(f"{dog.name}: ", end="") #?print_dog_name38 dog⟨Dog B⟩.speak() #?dog_speak39 dog⟨Dog B⟩.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self⟨Dog B⟩): #?speak_method80 """Make the sound loudly."""81 print(f"{self.soundWoof}!") #?print_loudoutputWoof!def whisper(self): #?whisper_method
pass 2 of 238 dog.speak() #?dog_speak39 dog⟨Dog B⟩.whisper() #?dog_whisper4041 # Mixin naming convention #?naming42 print("\n--- Naming Convention ---")43 print("Mixins typically end with 'Mixin':")44 print(" • LoggingMixin")45 print(" • SerializableMixin")46 print(" • ComparableMixin")47 print(" • RepresentationMixin")4849 print("\n=== Key Points ===")50 print("""51 1. Mixins add specific functionality52 2. Usually don't have __init__ (or minimal)53 3. Designed to be combined with other classes54 4. Name ends with 'Mixin' by convention55 5. Focus on ONE responsibility per mixin56 """)575859# RepresentationMixin - adds string representations #?repr_mixin60class RepresentationMixin: #?repr_mixin_class61 """Mixin that provides string representation methods."""6263 def get_info(self): #?get_info_method64 """Return formatted info string."""65 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) #?format_attrs66 return f"{self.__class__.__name__}({attrs})" #?return_info6768 def __repr__(self): #?repr_method69 """Return debug representation."""70 return self.get_info() #?return_repr717273# VoiceMixin - adds voice capabilities #?voice_mixin74class VoiceMixin: #?voice_mixin_class75 """Mixin that provides voice-related methods."""7677 sound = "..." #?default_sound7879 def speak(self): #?speak_method80 """Make the sound loudly."""81 print(f"{self.sound}!") #?print_loud8283 def whisper(self⟨Dog B⟩): #?whisper_method84 """Make the sound quietly."""85 print(f"({self.soundWoof.lower()})") #?print_quietoutput(woof) --- Naming Convention --- Mixins typically end with 'Mixin': • LoggingMixin • SerializableMixin • ComparableMixin • RepresentationMixin === Key Points === 1. Mixins add specific functionality 2. Usually don't have __init__ (or minimal) 3. Designed to be combined with other classes 4. Name ends with 'Mixin' by convention 5. Focus on ONE responsibility per mixinmain()
124if __name__ == "__main__":125 main()
sound ← (empty)
58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound→ (empty) = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound→ (empty) = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound→ (empty) = "Woof"def main():
3def main():4 print("=== Mixin Basics ===\n")56 # What is a mixin?7 print("--- What is a Mixin? ---")8 print("A small class that provides specific functionality")9 print("to be 'mixed into' other classes.\n")1011 # Simple mixin example12 print("--- Simple Mixin Example ---")1314 # Product with RepresentationMixin15 product = Product("Tablet", 349.99)16 print(f"Product info: {product.get_info()}")output=== Mixin Basics === --- What is a Mixin? --- A small class that provides specific functionality to be 'mixed into' other classes. --- Simple Mixin Example ---self.name ← Tablet, self.price ← 349.99, product ← Product(name='Tablet', price=349.99)
14 # Product with RepresentationMixin15 product→ Product(name='Tablet', price=349.99) = Product("Tablet", 349.99)16 print(f"Product info: {productProduct(name='Tablet', price=349.99).get_info()}")17 print(f"Repr: {product!r}")1819 # Order with RepresentationMixin20 order = Order("ORD-001", 5)21 print(f"Order info: {order.get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Whiskers")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(selfProduct(), nameTablet: str, price349.99: float):91 self.name→ Tablet = nameTablet92 self.price→ 349.99 = price349.99attrs ← name='Tablet', price=349.99
pass 1 of 461def get_info(selfProduct(name='Tablet', price=349.99)):62 """Return formatted info string."""63 attrs→ name='Tablet', price=349.99 = ", ".join(f"{k(empty)}={v(empty)!r}" for k, v in self.__dict__{'name': 'Tablet', 'price': 349.99}.items())64 return f"{self.__class__.__name__Product}({attrsname='Tablet', price=349.99})"All 4 passes — pass 1 is the card above pass selfself.__dict__self.__class__.__name__attrs1 Product(name='Tablet', price=349.99) {'name': 'Tablet', 'price': 349.99} Product name='Tablet', price=349.99 2 Product(name='Tablet', price=349.99) {'name': 'Tablet', 'price': 349.99} Product name='Tablet', price=349.99 3 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 4 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 print(f"Product info: {product.get_info()}")
15product = Product("Tablet", 349.99)16print(f"Product info: {productProduct(name='Tablet', price=349.99).get_info()}")17print(f"Repr: {productProduct(name='Tablet', price=349.99)!r}")outputProduct info: Product(name='Tablet', price=349.99)print(f"Repr: {product!r}")
16print(f"Product info: {product.get_info()}")17print(f"Repr: {productProduct(name='Tablet', price=349.99)!r}")1819# Order with RepresentationMixin20order = Order("ORD-001", 5)21print(f"Order info: {order.get_info()}")outputRepr: Product(name='Tablet', price=349.99)self.order_id ← ORD-001, self.quantity ← 5, order ← Order(order_id='ORD-001', quantity=5)
19 # Order with RepresentationMixin20 order→ Order(order_id='ORD-001', quantity=5) = Order("ORD-001", 5)21 print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Whiskers")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(selfOrder(), order_idORD-001: str, quantity5: int):99 self.order_id→ ORD-001 = order_idORD-001100 self.quantity→ 5 = quantity5print(f"Order info: {order.get_info()}")
20order = Order("ORD-001", 5)21print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")outputOrder info: Order(order_id='ORD-001', quantity=5)print(f"Repr: {order!r}")
21print(f"Order info: {order.get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")2324# Mixin adds functionality to different classes25print("\n--- Same Mixin, Different Classes ---")2627# Cat with VoiceMixin28cat = Cat("Whiskers")29print(f"{cat.name}: ", end="")outputRepr: Order(order_id='ORD-001', quantity=5) --- Same Mixin, Different Classes ---self.name ← Whiskers, cat ← ⟨Cat A⟩
27 # Cat with VoiceMixin28 cat→ ⟨Cat A⟩ = Cat("Whiskers")29 print(f"{cat.nameWhiskers}: ", end="")30 cat⟨Cat A⟩.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self⟨Cat A⟩, nameWhiskers: str):110 self.name→ Whiskers = nameWhiskersoutputWhiskers:def speak(self):
pass 1 of 229 print(f"{cat.name}: ", end="")30 cat⟨Cat A⟩.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Cat A⟩):78 """Make the sound loudly."""79 print(f"{self.soundMeow}!")outputMeow!def whisper(self):
pass 1 of 230 cat.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Cat A⟩):82 """Make the sound quietly."""83 print(f"({self.soundMeow.lower()})")output(meow)self.name ← Buddy, dog ← ⟨Dog B⟩
33 # Dog with VoiceMixin34 dog→ ⟨Dog B⟩ = Dog("Buddy")35 print(f"{dog.nameBuddy}: ", end="")36 dog⟨Dog B⟩.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound = "Woof"117118 def __init__(self⟨Dog B⟩, nameBuddy: str):119 self.name→ Buddy = nameBuddyoutputBuddy:def speak(self):
pass 2 of 235 print(f"{dog.name}: ", end="")36 dog⟨Dog B⟩.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Dog B⟩):78 """Make the sound loudly."""79 print(f"{self.soundWoof}!")outputWoof!def whisper(self):
pass 2 of 236 dog.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Dog B⟩):82 """Make the sound quietly."""83 print(f"({self.soundWoof.lower()})")output(woof) --- Naming Convention --- Mixins typically end with 'Mixin': • LoggingMixin • SerializableMixin • ComparableMixin • RepresentationMixin === Key Points === 1. Mixins add specific functionality 2. Usually don't have __init__ (or minimal) 3. Designed to be combined with other classes 4. Name ends with 'Mixin' by convention 5. Focus on ONE responsibility per mixinmain()
122if __name__ == "__main__":123 main()
sound ← (empty)
58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound→ (empty) = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound→ (empty) = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound→ (empty) = "Woof"def main():
3def main():4 print("=== Mixin Basics ===\n")56 # What is a mixin?7 print("--- What is a Mixin? ---")8 print("A small class that provides specific functionality")9 print("to be 'mixed into' other classes.\n")1011 # Simple mixin example12 print("--- Simple Mixin Example ---")1314 # Product with RepresentationMixin15 product = Product("Monitor", 229.99)16 print(f"Product info: {product.get_info()}")output=== Mixin Basics === --- What is a Mixin? --- A small class that provides specific functionality to be 'mixed into' other classes. --- Simple Mixin Example ---self.name ← Monitor, self.price ← 229.99, product ← Product(name='Monitor', price=229.99)
14 # Product with RepresentationMixin15 product→ Product(name='Monitor', price=229.99) = Product("Monitor", 229.99)16 print(f"Product info: {productProduct(name='Monitor', price=229.99).get_info()}")17 print(f"Repr: {product!r}")1819 # Order with RepresentationMixin20 order = Order("ORD-001", 5)21 print(f"Order info: {order.get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Whiskers")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(selfProduct(), nameMonitor: str, price229.99: float):91 self.name→ Monitor = nameMonitor92 self.price→ 229.99 = price229.99attrs ← name='Monitor', price=229.99
pass 1 of 461def get_info(selfProduct(name='Monitor', price=229.99)):62 """Return formatted info string."""63 attrs→ name='Monitor', price=229.99 = ", ".join(f"{k(empty)}={v(empty)!r}" for k, v in self.__dict__{'name': 'Monitor', 'price': 229.99}.items())64 return f"{self.__class__.__name__Product}({attrsname='Monitor', price=229.99})"All 4 passes — pass 1 is the card above pass selfself.__dict__self.__class__.__name__attrs1 Product(name='Monitor', price=229.99) {'name': 'Monitor', 'price': 229.99} Product name='Monitor', price=229.99 2 Product(name='Monitor', price=229.99) {'name': 'Monitor', 'price': 229.99} Product name='Monitor', price=229.99 3 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 4 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 print(f"Product info: {product.get_info()}")
15product = Product("Monitor", 229.99)16print(f"Product info: {productProduct(name='Monitor', price=229.99).get_info()}")17print(f"Repr: {productProduct(name='Monitor', price=229.99)!r}")outputProduct info: Product(name='Monitor', price=229.99)print(f"Repr: {product!r}")
16print(f"Product info: {product.get_info()}")17print(f"Repr: {productProduct(name='Monitor', price=229.99)!r}")1819# Order with RepresentationMixin20order = Order("ORD-001", 5)21print(f"Order info: {order.get_info()}")outputRepr: Product(name='Monitor', price=229.99)self.order_id ← ORD-001, self.quantity ← 5, order ← Order(order_id='ORD-001', quantity=5)
19 # Order with RepresentationMixin20 order→ Order(order_id='ORD-001', quantity=5) = Order("ORD-001", 5)21 print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Whiskers")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(selfOrder(), order_idORD-001: str, quantity5: int):99 self.order_id→ ORD-001 = order_idORD-001100 self.quantity→ 5 = quantity5print(f"Order info: {order.get_info()}")
20order = Order("ORD-001", 5)21print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")outputOrder info: Order(order_id='ORD-001', quantity=5)print(f"Repr: {order!r}")
21print(f"Order info: {order.get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")2324# Mixin adds functionality to different classes25print("\n--- Same Mixin, Different Classes ---")2627# Cat with VoiceMixin28cat = Cat("Whiskers")29print(f"{cat.name}: ", end="")outputRepr: Order(order_id='ORD-001', quantity=5) --- Same Mixin, Different Classes ---self.name ← Whiskers, cat ← ⟨Cat A⟩
27 # Cat with VoiceMixin28 cat→ ⟨Cat A⟩ = Cat("Whiskers")29 print(f"{cat.nameWhiskers}: ", end="")30 cat⟨Cat A⟩.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self⟨Cat A⟩, nameWhiskers: str):110 self.name→ Whiskers = nameWhiskersoutputWhiskers:def speak(self):
pass 1 of 229 print(f"{cat.name}: ", end="")30 cat⟨Cat A⟩.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Cat A⟩):78 """Make the sound loudly."""79 print(f"{self.soundMeow}!")outputMeow!def whisper(self):
pass 1 of 230 cat.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Cat A⟩):82 """Make the sound quietly."""83 print(f"({self.soundMeow.lower()})")output(meow)self.name ← Buddy, dog ← ⟨Dog B⟩
33 # Dog with VoiceMixin34 dog→ ⟨Dog B⟩ = Dog("Buddy")35 print(f"{dog.nameBuddy}: ", end="")36 dog⟨Dog B⟩.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound = "Woof"117118 def __init__(self⟨Dog B⟩, nameBuddy: str):119 self.name→ Buddy = nameBuddyoutputBuddy:def speak(self):
pass 2 of 235 print(f"{dog.name}: ", end="")36 dog⟨Dog B⟩.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Dog B⟩):78 """Make the sound loudly."""79 print(f"{self.soundWoof}!")outputWoof!def whisper(self):
pass 2 of 236 dog.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Dog B⟩):82 """Make the sound quietly."""83 print(f"({self.soundWoof.lower()})")output(woof) --- Naming Convention --- Mixins typically end with 'Mixin': • LoggingMixin • SerializableMixin • ComparableMixin • RepresentationMixin === Key Points === 1. Mixins add specific functionality 2. Usually don't have __init__ (or minimal) 3. Designed to be combined with other classes 4. Name ends with 'Mixin' by convention 5. Focus on ONE responsibility per mixinmain()
122if __name__ == "__main__":123 main()
sound ← (empty)
58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound→ (empty) = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound→ (empty) = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound→ (empty) = "Woof"def main():
3def main():4 print("=== Mixin Basics ===\n")56 # What is a mixin?7 print("--- What is a Mixin? ---")8 print("A small class that provides specific functionality")9 print("to be 'mixed into' other classes.\n")1011 # Simple mixin example12 print("--- Simple Mixin Example ---")1314 # Product with RepresentationMixin15 product = Product("Laptop", 999.99)16 print(f"Product info: {product.get_info()}")output=== Mixin Basics === --- What is a Mixin? --- A small class that provides specific functionality to be 'mixed into' other classes. --- Simple Mixin Example ---self.name ← Laptop, self.price ← 999.99, product ← Product(name='Laptop', price=999.99)
14 # Product with RepresentationMixin15 product→ Product(name='Laptop', price=999.99) = Product("Laptop", 999.99)16 print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}")17 print(f"Repr: {product!r}")1819 # Order with RepresentationMixin20 order = Order("ORD-001", 5)21 print(f"Order info: {order.get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Misty")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(selfProduct(), nameLaptop: str, price999.99: float):91 self.name→ Laptop = nameLaptop92 self.price→ 999.99 = price999.99attrs ← name='Laptop', price=999.99
pass 1 of 461def get_info(selfProduct(name='Laptop', price=999.99)):62 """Return formatted info string."""63 attrs→ name='Laptop', price=999.99 = ", ".join(f"{k(empty)}={v(empty)!r}" for k, v in self.__dict__{'name': 'Laptop', 'price': 999.99}.items())64 return f"{self.__class__.__name__Product}({attrsname='Laptop', price=999.99})"All 4 passes — pass 1 is the card above pass selfself.__dict__self.__class__.__name__attrs1 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 2 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 3 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 4 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 print(f"Product info: {product.get_info()}")
15product = Product("Laptop", 999.99)16print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}")17print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}")outputProduct info: Product(name='Laptop', price=999.99)print(f"Repr: {product!r}")
16print(f"Product info: {product.get_info()}")17print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}")1819# Order with RepresentationMixin20order = Order("ORD-001", 5)21print(f"Order info: {order.get_info()}")outputRepr: Product(name='Laptop', price=999.99)self.order_id ← ORD-001, self.quantity ← 5, order ← Order(order_id='ORD-001', quantity=5)
19 # Order with RepresentationMixin20 order→ Order(order_id='ORD-001', quantity=5) = Order("ORD-001", 5)21 print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Misty")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(selfOrder(), order_idORD-001: str, quantity5: int):99 self.order_id→ ORD-001 = order_idORD-001100 self.quantity→ 5 = quantity5print(f"Order info: {order.get_info()}")
20order = Order("ORD-001", 5)21print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")outputOrder info: Order(order_id='ORD-001', quantity=5)print(f"Repr: {order!r}")
21print(f"Order info: {order.get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")2324# Mixin adds functionality to different classes25print("\n--- Same Mixin, Different Classes ---")2627# Cat with VoiceMixin28cat = Cat("Misty")29print(f"{cat.name}: ", end="")outputRepr: Order(order_id='ORD-001', quantity=5) --- Same Mixin, Different Classes ---self.name ← Misty, cat ← ⟨Cat A⟩
27 # Cat with VoiceMixin28 cat→ ⟨Cat A⟩ = Cat("Misty")29 print(f"{cat.nameMisty}: ", end="")30 cat⟨Cat A⟩.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self⟨Cat A⟩, nameMisty: str):110 self.name→ Misty = nameMistyoutputMisty:def speak(self):
pass 1 of 229 print(f"{cat.name}: ", end="")30 cat⟨Cat A⟩.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Cat A⟩):78 """Make the sound loudly."""79 print(f"{self.soundMeow}!")outputMeow!def whisper(self):
pass 1 of 230 cat.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Cat A⟩):82 """Make the sound quietly."""83 print(f"({self.soundMeow.lower()})")output(meow)self.name ← Buddy, dog ← ⟨Dog B⟩
33 # Dog with VoiceMixin34 dog→ ⟨Dog B⟩ = Dog("Buddy")35 print(f"{dog.nameBuddy}: ", end="")36 dog⟨Dog B⟩.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound = "Woof"117118 def __init__(self⟨Dog B⟩, nameBuddy: str):119 self.name→ Buddy = nameBuddyoutputBuddy:def speak(self):
pass 2 of 235 print(f"{dog.name}: ", end="")36 dog⟨Dog B⟩.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Dog B⟩):78 """Make the sound loudly."""79 print(f"{self.soundWoof}!")outputWoof!def whisper(self):
pass 2 of 236 dog.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Dog B⟩):82 """Make the sound quietly."""83 print(f"({self.soundWoof.lower()})")output(woof) --- Naming Convention --- Mixins typically end with 'Mixin': • LoggingMixin • SerializableMixin • ComparableMixin • RepresentationMixin === Key Points === 1. Mixins add specific functionality 2. Usually don't have __init__ (or minimal) 3. Designed to be combined with other classes 4. Name ends with 'Mixin' by convention 5. Focus on ONE responsibility per mixinmain()
122if __name__ == "__main__":123 main()
sound ← (empty)
58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound→ (empty) = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound→ (empty) = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound→ (empty) = "Woof"def main():
3def main():4 print("=== Mixin Basics ===\n")56 # What is a mixin?7 print("--- What is a Mixin? ---")8 print("A small class that provides specific functionality")9 print("to be 'mixed into' other classes.\n")1011 # Simple mixin example12 print("--- Simple Mixin Example ---")1314 # Product with RepresentationMixin15 product = Product("Laptop", 999.99)16 print(f"Product info: {product.get_info()}")output=== Mixin Basics === --- What is a Mixin? --- A small class that provides specific functionality to be 'mixed into' other classes. --- Simple Mixin Example ---self.name ← Laptop, self.price ← 999.99, product ← Product(name='Laptop', price=999.99)
14 # Product with RepresentationMixin15 product→ Product(name='Laptop', price=999.99) = Product("Laptop", 999.99)16 print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}")17 print(f"Repr: {product!r}")1819 # Order with RepresentationMixin20 order = Order("ORD-001", 5)21 print(f"Order info: {order.get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Shadow")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(selfProduct(), nameLaptop: str, price999.99: float):91 self.name→ Laptop = nameLaptop92 self.price→ 999.99 = price999.99attrs ← name='Laptop', price=999.99
pass 1 of 461def get_info(selfProduct(name='Laptop', price=999.99)):62 """Return formatted info string."""63 attrs→ name='Laptop', price=999.99 = ", ".join(f"{k(empty)}={v(empty)!r}" for k, v in self.__dict__{'name': 'Laptop', 'price': 999.99}.items())64 return f"{self.__class__.__name__Product}({attrsname='Laptop', price=999.99})"All 4 passes — pass 1 is the card above pass selfself.__dict__self.__class__.__name__attrs1 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 2 Product(name='Laptop', price=999.99) {'name': 'Laptop', 'price': 999.99} Product name='Laptop', price=999.99 3 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 4 Order(order_id='ORD-001', quantity=5) {'order_id': 'ORD-001', 'quantity': 5} Order order_id='ORD-001', quantity=5 print(f"Product info: {product.get_info()}")
15product = Product("Laptop", 999.99)16print(f"Product info: {productProduct(name='Laptop', price=999.99).get_info()}")17print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}")outputProduct info: Product(name='Laptop', price=999.99)print(f"Repr: {product!r}")
16print(f"Product info: {product.get_info()}")17print(f"Repr: {productProduct(name='Laptop', price=999.99)!r}")1819# Order with RepresentationMixin20order = Order("ORD-001", 5)21print(f"Order info: {order.get_info()}")outputRepr: Product(name='Laptop', price=999.99)self.order_id ← ORD-001, self.quantity ← 5, order ← Order(order_id='ORD-001', quantity=5)
19 # Order with RepresentationMixin20 order→ Order(order_id='ORD-001', quantity=5) = Order("ORD-001", 5)21 print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22 print(f"Repr: {order!r}")2324 # Mixin adds functionality to different classes25 print("\n--- Same Mixin, Different Classes ---")2627 # Cat with VoiceMixin28 cat = Cat("Shadow")29 print(f"{cat.name}: ", end="")30 cat.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(selfOrder(), order_idORD-001: str, quantity5: int):99 self.order_id→ ORD-001 = order_idORD-001100 self.quantity→ 5 = quantity5print(f"Order info: {order.get_info()}")
20order = Order("ORD-001", 5)21print(f"Order info: {orderOrder(order_id='ORD-001', quantity=5).get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")outputOrder info: Order(order_id='ORD-001', quantity=5)print(f"Repr: {order!r}")
21print(f"Order info: {order.get_info()}")22print(f"Repr: {orderOrder(order_id='ORD-001', quantity=5)!r}")2324# Mixin adds functionality to different classes25print("\n--- Same Mixin, Different Classes ---")2627# Cat with VoiceMixin28cat = Cat("Shadow")29print(f"{cat.name}: ", end="")outputRepr: Order(order_id='ORD-001', quantity=5) --- Same Mixin, Different Classes ---self.name ← Shadow, cat ← ⟨Cat A⟩
27 # Cat with VoiceMixin28 cat→ ⟨Cat A⟩ = Cat("Shadow")29 print(f"{cat.nameShadow}: ", end="")30 cat⟨Cat A⟩.speak()31 cat.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self⟨Cat A⟩, nameShadow: str):110 self.name→ Shadow = nameShadowoutputShadow:def speak(self):
pass 1 of 229 print(f"{cat.name}: ", end="")30 cat⟨Cat A⟩.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Cat A⟩):78 """Make the sound loudly."""79 print(f"{self.soundMeow}!")outputMeow!def whisper(self):
pass 1 of 230 cat.speak()31 cat⟨Cat A⟩.whisper()3233 # Dog with VoiceMixin34 dog = Dog("Buddy")35 print(f"{dog.name}: ", end="")36 dog.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Cat A⟩):82 """Make the sound quietly."""83 print(f"({self.soundMeow.lower()})")output(meow)self.name ← Buddy, dog ← ⟨Dog B⟩
33 # Dog with VoiceMixin34 dog→ ⟨Dog B⟩ = Dog("Buddy")35 print(f"{dog.nameBuddy}: ", end="")36 dog⟨Dog B⟩.speak()37 dog.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self):82 """Make the sound quietly."""83 print(f"({self.sound.lower()})")848586# Classes using RepresentationMixin87class Product(RepresentationMixin):88 """Product class with representation mixin."""8990 def __init__(self, name: str, price: float):91 self.name = name92 self.price = price939495class Order(RepresentationMixin):96 """Order class with representation mixin."""9798 def __init__(self, order_id: str, quantity: int):99 self.order_id = order_id100 self.quantity = quantity101102103# Classes using VoiceMixin104class Cat(VoiceMixin):105 """Cat class with voice mixin."""106107 sound = "Meow"108109 def __init__(self, name: str):110 self.name = name111112113class Dog(VoiceMixin):114 """Dog class with voice mixin."""115116 sound = "Woof"117118 def __init__(self⟨Dog B⟩, nameBuddy: str):119 self.name→ Buddy = nameBuddyoutputBuddy:def speak(self):
pass 2 of 235 print(f"{dog.name}: ", end="")36 dog⟨Dog B⟩.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self⟨Dog B⟩):78 """Make the sound loudly."""79 print(f"{self.soundWoof}!")outputWoof!def whisper(self):
pass 2 of 236 dog.speak()37 dog⟨Dog B⟩.whisper()3839 # Mixin naming convention40 print("\n--- Naming Convention ---")41 print("Mixins typically end with 'Mixin':")42 print(" • LoggingMixin")43 print(" • SerializableMixin")44 print(" • ComparableMixin")45 print(" • RepresentationMixin")4647 print("\n=== Key Points ===")48 print("""49 1. Mixins add specific functionality50 2. Usually don't have __init__ (or minimal)51 3. Designed to be combined with other classes52 4. Name ends with 'Mixin' by convention53 5. Focus on ONE responsibility per mixin54 """)555657# RepresentationMixin - adds string representations58class RepresentationMixin:59 """Mixin that provides string representation methods."""6061 def get_info(self):62 """Return formatted info string."""63 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())64 return f"{self.__class__.__name__}({attrs})"6566 def __repr__(self):67 """Return debug representation."""68 return self.get_info()697071# VoiceMixin - adds voice capabilities72class VoiceMixin:73 """Mixin that provides voice-related methods."""7475 sound = "..."7677 def speak(self):78 """Make the sound loudly."""79 print(f"{self.sound}!")8081 def whisper(self⟨Dog B⟩):82 """Make the sound quietly."""83 print(f"({self.soundWoof.lower()})")output(woof) --- Naming Convention --- Mixins typically end with 'Mixin': • LoggingMixin • SerializableMixin • ComparableMixin • RepresentationMixin === Key Points === 1. Mixins add specific functionality 2. Usually don't have __init__ (or minimal) 3. Designed to be combined with other classes 4. Name ends with 'Mixin' by convention 5. Focus on ONE responsibility per mixinmain()
122if __name__ == "__main__":123 main()
Mixins add single behavior. Usually no __init__, just methods.
Composing mixins
Combine multiple mixins for multiple capabilities.
# Composing Multiple Mixins
from datetime import datetime
def main():
print("=== Composing Multiple Mixins ===\n")
# Multiple mixins in one class
print("--- Multiple Mixins Combined ---")
# DataRecord with multiple mixins
record = DataRecord(1, "Sample data", "active")
print("DataRecord capabilities:")
print(f" As dict: {record.to_dict()}")
print(f" Timestamp: {record.created_at}")
record.log("Record created")
# Compare with DataRecord without mixins
print("\n--- Without Mixins vs With Mixins ---")
simple = SimpleRecord(1, "Simple")
print(f"SimpleRecord: {simple}")
enhanced = EnhancedRecord(1, "Enhanced")
print(f"EnhancedRecord: {enhanced}")
print(f" as_json: {enhanced.as_json()}")
print(f" created_at: {enhanced.created_at}")
# Mixin order matters
print("\n--- Mixin Order (MRO) ---")
print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):")
print(f"MRO: {[c.__name__ for c in DataRecord.__mro__]}")
# User with all mixins
print("\n--- User with Multiple Mixins ---")
user = User(42, "alice", "alice@example.com")
print(f"User dict: {user.to_dict()}")
print(f"Has timestamp: {hasattr(user, 'created_at')}")
user.log("User loaded from database")
# Selective mixin usage
print("\n--- Selective Mixin Usage ---")
# LogOnly class only has logging
logger = LogOnly("Logger instance")
logger.log("Testing selective mixin")
print(f"Has to_dict? {hasattr(logger, 'to_dict')}")
print(f"Has created_at? {hasattr(logger, 'created_at')}")
print("\n=== Key Points ===")
print("""
1. Combine multiple mixins for rich functionality
2. Each mixin adds specific capability
3. Order in inheritance affects MRO
4. Pick only the mixins you need
5. Mixins should be independent (no mixin depends on another)
""")
# Define individual mixins
class DictMixin:
"""Mixin for dictionary conversion."""
def to_dict(self) -> dict:
"""Convert object to dictionary."""
return {k: v for k, v in self.__dict__.items()
if not k.startswith('_')}
def as_json(self) -> str:
"""Return JSON-like string representation."""
import json
return json.dumps(self.to_dict(), default=str)
class TimestampMixin:
"""Mixin for automatic timestamps."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.created_at = datetime(2025, 1, 15, 10, 30)
class LoggingMixin:
"""Mixin for logging capability."""
def log(self, message: str):
"""Log a message with class name prefix."""
print(f"[{self.__class__.__name__}] {message}")
# Class combining multiple mixins
class DataRecord(DictMixin, TimestampMixin, LoggingMixin):
"""Data record with dict, timestamp, and logging capabilities."""
def __init__(self, record_id: int, data: str, status: str):
super().__init__()
self.record_id = record_id
self.data = data
self.status = status
# Comparison: without vs with mixins
class SimpleRecord:
"""Record without any mixins."""
def __init__(self, record_id: int, data: str):
self.record_id = record_id
self.data = data
def __str__(self):
return f"SimpleRecord({self.record_id}, {self.data})"
class EnhancedRecord(DictMixin, TimestampMixin):
"""Record with dict and timestamp mixins."""
def __init__(self, record_id: int, data: str):
super().__init__()
self.record_id = record_id
self.data = data
def __str__(self):
return f"EnhancedRecord({self.record_id}, {self.data})"
# User class with all mixins
class User(DictMixin, TimestampMixin, LoggingMixin):
"""User with full mixin support."""
def __init__(self, user_id: int, username: str, email: str):
super().__init__()
self.user_id = user_id
self.username = username
self.email = email
# Selective mixin usage
class LogOnly(LoggingMixin):
"""Class with only logging mixin."""
def __init__(self, name: str):
self.name = name
if __name__ == "__main__":
main()
"""Mixin for dictionary conversion."""
65class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_id102 self.data = data #?set_data103 self.status = status #?set_status104105106# Comparison: without vs with mixins #?comparison_classes107108class SimpleRecord: #?simple_record109 """Record without any mixins."""110111 def __init__(self, record_id: int, data: str): #?simple_init112 self.record_id = record_id #?simple_record_id113 self.data = data #?simple_data114115 def __str__(self): #?simple_str116 return f"SimpleRecord({self.record_id}, {self.data})" #?simple_return117118119class EnhancedRecord(DictMixin, TimestampMixin): #?enhanced_record120 """Record with dict and timestamp mixins."""121122 def __init__(self, record_id: int, data: str): #?enhanced_init123 super().__init__() #?enhanced_super124 self.record_id = record_id #?enhanced_record_id125 self.data = data #?enhanced_data126127 def __str__(self): #?enhanced_str128 return f"EnhancedRecord({self.record_id}, {self.data})" #?enhanced_return129130131# User class with all mixins #?user_class132class User(DictMixin, TimestampMixin, LoggingMixin): #?user_definition133 """User with full mixin support."""134135 def __init__(self, user_id: int, username: str, email: str): #?user_init136 super().__init__() #?user_super137 self.user_id = user_id #?set_user_id138 self.username = username #?set_username139 self.email = email #?set_email140141142# Selective mixin usage #?selective_class143class LogOnly(LoggingMixin): #?logonly_class144 """Class with only logging mixin."""def main():
5def main():6 print("=== Composing Multiple Mixins ===\n")78 # Multiple mixins in one class #?multiple_mixins9 print("--- Multiple Mixins Combined ---")output=== Composing Multiple Mixins === --- Multiple Mixins Combined ---def __init__(self, record_id: int, data: str, status: str): #?data_rec…
99def __init__(self⟨DataRecord A⟩, record_id1: int, dataSample data: str, statusactive: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_idself.created_at ← 2025-01-15 10:30:00
pass 1 of 382def __init__(self⟨DataRecord A⟩, *args(), **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at→ 2025-01-15 10:30:00 = datetime(2025, 1, 15, 10, 30) #?set_created_atAll 3 passes — pass 1 is the card above pass selfself.created_at1 ⟨DataRecord A⟩ 2025-01-15 10:30:00 2 (empty) 2025-01-15 10:30:00 3 ⟨User B⟩ 2025-01-15 10:30:00 self.record_id ← 1, self.data ← Sample data, self.status ← active
14 print("DataRecord capabilities:") #?record_capabilities15 print(f" As dict: {record⟨DataRecord A⟩.to_dict()}") #?record_to_dict16 print(f" Timestamp: {record.created_at}") #?record_timestamp17 record.log("Record created") #?record_log1819 # Compare with DataRecord without mixins #?without_mixins20 print("\n--- Without Mixins vs With Mixins ---")2122 simple = SimpleRecord(1, "Simple") #?create_simple23 print(f"SimpleRecord: {simple}") #?print_simple2425 enhanced = EnhancedRecord(1, "Enhanced") #?create_enhanced26 print(f"EnhancedRecord: {enhanced}") #?print_enhanced27 print(f" as_json: {enhanced.as_json()}") #?enhanced_json28 print(f" created_at: {enhanced.created_at}") #?enhanced_created2930 # Mixin order matters #?order_matters31 print("\n--- Mixin Order (MRO) ---")3233 print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):") #?print_class_def34 print(f"MRO: {[c.__name__ for c in DataRecord.__mro__]}") #?print_mro3536 # User with all mixins #?user_demo37 print("\n--- User with Multiple Mixins ---")3839 user = User(42, "alice", "alice@example.com") #?create_user40 print(f"User dict: {user.to_dict()}") #?user_dict41 print(f"Has timestamp: {hasattr(user, 'created_at')}") #?user_has_timestamp42 user.log("User loaded from database") #?user_log4344 # Selective mixin usage #?selective45 print("\n--- Selective Mixin Usage ---")4647 # LogOnly class only has logging #?logonly_demo48 logger = LogOnly("Logger instance") #?create_logonly49 logger.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id→ 1 = record_id1 #?set_record_id102 self.data→ Sample data = dataSample data #?set_data103 self.status→ active = statusactive #?set_statusoutputDataRecord capabilities:def to_dict(self) -> dict: #?to_dict_method
pass 1 of 368def to_dict(self⟨DataRecord A⟩) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k(empty): v(empty) for k, v in self.__dict__{'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'record_id': 1, 'data': 'Sample data', 'status': 'active'}.items() #?dict_comprehension71 if not k(empty).startswith('_')} #?skip_privateAll 3 passes — pass 1 is the card above pass selfself.__dict__1 ⟨DataRecord A⟩ {'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'record_id': 1, 'data': 'Sample data', 'status': 'active'} 2 EnhancedRecord(1, Enhanced) {'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'record_id': 1, 'data': 'Enhanced'} 3 ⟨User B⟩ {'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'user_id': 42, 'username': 'alice', 'email': 'alice@example.com'} print(f" As dict: {record.to_dict()}") #?record_to_dict
14print("DataRecord capabilities:") #?record_capabilities15print(f" As dict: {record⟨DataRecord A⟩.to_dict()}") #?record_to_dict16print(f" Timestamp: {record.created_at2025-01-15 10:30:00}") #?record_timestamp17record.log("Record created") #?record_logoutput As dict: {'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'record_id': 1, 'data': 'Sample data', 'status': 'active'} Timestamp: 2025-01-15 10:30:00def log(self, message: str): #?log_method
pass 1 of 319 # Compare with DataRecord without mixins #?without_mixins20 print("\n--- Without Mixins vs With Mixins ---")2122 simple = SimpleRecord(1, "Simple") #?create_simple23 print(f"SimpleRecord: {simple}") #?print_simple2425 enhanced = EnhancedRecord(1, "Enhanced") #?create_enhanced26 print(f"EnhancedRecord: {enhanced}") #?print_enhanced27 print(f" as_json: {enhanced.as_json()}") #?enhanced_json28 print(f" created_at: {enhanced.created_at}") #?enhanced_created2930 # Mixin order matters #?order_matters31 print("\n--- Mixin Order (MRO) ---")3233 print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):") #?print_class_def34 print(f"MRO: {[c.__name__ for c in DataRecord.__mro__]}") #?print_mro3536 # User with all mixins #?user_demo37 print("\n--- User with Multiple Mixins ---")3839 user = User(42, "alice", "alice@example.com") #?create_user40 print(f"User dict: {user.to_dict()}") #?user_dict41 print(f"Has timestamp: {hasattr(user, 'created_at')}") #?user_has_timestamp42 user.log("User loaded from database") #?user_log4344 # Selective mixin usage #?selective45 print("\n--- Selective Mixin Usage ---")4647 # LogOnly class only has logging #?logonly_demo48 logger = LogOnly("Logger instance") #?create_logonly49 logger.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self⟨DataRecord A⟩, messageRecord created: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__DataRecord}] {messageRecord created}") #?print_logoutput[DataRecord] Record created --- Without Mixins vs With Mixins ---All 3 passes — pass 1 is the card above pass selfmessageself.__class__.__name__record_iddatausernameself.record_idself.datasimpleself.namelogger1 ⟨DataRecord A⟩ Record created DataRecord 1 Simple — — 1 Simple SimpleRecord(1, Simple) — — 2 ⟨User B⟩ User loaded from database User — — ⟨User B⟩ Logger instance — — — Logger instance ⟨LogOnly C⟩ 3 ⟨LogOnly C⟩ Testing selective mixin LogOnly — — — — — — — — ⟨LogOnly C⟩ self.record_id ← 1, self.data ← Simple, simple ← SimpleRecord(1, Simple)
22 simple→ SimpleRecord(1, Simple) = SimpleRecord(1, "Simple") #?create_simple23 print(f"SimpleRecord: {simpleSimpleRecord(1, Simple)}") #?print_simple2425 enhanced = EnhancedRecord(1, "Enhanced") #?create_enhanced26 print(f"EnhancedRecord: {enhanced}") #?print_enhanced27 print(f" as_json: {enhanced.as_json()}") #?enhanced_json28 print(f" created_at: {enhanced.created_at}") #?enhanced_created2930 # Mixin order matters #?order_matters31 print("\n--- Mixin Order (MRO) ---")3233 print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):") #?print_class_def34 print(f"MRO: {[c.__name__ for c in DataRecord.__mro__]}") #?print_mro3536 # User with all mixins #?user_demo37 print("\n--- User with Multiple Mixins ---")3839 user = User(42, "alice", "alice@example.com") #?create_user40 print(f"User dict: {user.to_dict()}") #?user_dict41 print(f"Has timestamp: {hasattr(user, 'created_at')}") #?user_has_timestamp42 user.log("User loaded from database") #?user_log4344 # Selective mixin usage #?selective45 print("\n--- Selective Mixin Usage ---")4647 # LogOnly class only has logging #?logonly_demo48 logger = LogOnly("Logger instance") #?create_logonly49 logger.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_id102 self.data = data #?set_data103 self.status = status #?set_status104105106# Comparison: without vs with mixins #?comparison_classes107108class SimpleRecord: #?simple_record109 """Record without any mixins."""110111 def __init__(self(empty), record_id1: int, dataSimple: str): #?simple_init112 self.record_id→ 1 = record_id1 #?simple_record_id113 self.data→ Simple = dataSimple #?simple_dataoutputSimpleRecord: SimpleRecord(1, Simple)def __init__(self, record_id: int, data: str): #?enhanced_init
122def __init__(self(empty), record_id1: int, dataEnhanced: str): #?enhanced_init123 super().__init__() #?enhanced_super124 self.record_id = record_id #?enhanced_record_idself.record_id ← 1, self.data ← Enhanced, enhanced ← EnhancedRecord(1, Enhanced)
25 enhanced→ EnhancedRecord(1, Enhanced) = EnhancedRecord(1, "Enhanced") #?create_enhanced26 print(f"EnhancedRecord: {enhancedEnhancedRecord(1, Enhanced)}") #?print_enhanced27 print(f" as_json: {enhancedEnhancedRecord(1, Enhanced).as_json()}") #?enhanced_json28 print(f" created_at: {enhanced.created_at}") #?enhanced_created2930 # Mixin order matters #?order_matters31 print("\n--- Mixin Order (MRO) ---")3233 print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):") #?print_class_def34 print(f"MRO: {[c.__name__ for c in DataRecord.__mro__]}") #?print_mro3536 # User with all mixins #?user_demo37 print("\n--- User with Multiple Mixins ---")3839 user = User(42, "alice", "alice@example.com") #?create_user40 print(f"User dict: {user.to_dict()}") #?user_dict41 print(f"Has timestamp: {hasattr(user, 'created_at')}") #?user_has_timestamp42 user.log("User loaded from database") #?user_log4344 # Selective mixin usage #?selective45 print("\n--- Selective Mixin Usage ---")4647 # LogOnly class only has logging #?logonly_demo48 logger = LogOnly("Logger instance") #?create_logonly49 logger.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_id102 self.data = data #?set_data103 self.status = status #?set_status104105106# Comparison: without vs with mixins #?comparison_classes107108class SimpleRecord: #?simple_record109 """Record without any mixins."""110111 def __init__(self, record_id: int, data: str): #?simple_init112 self.record_id = record_id #?simple_record_id113 self.data = data #?simple_data114115 def __str__(self): #?simple_str116 return f"SimpleRecord({self.record_id}, {self.data})" #?simple_return117118119class EnhancedRecord(DictMixin, TimestampMixin): #?enhanced_record120 """Record with dict and timestamp mixins."""121122 def __init__(self, record_id: int, data: str): #?enhanced_init123 super().__init__() #?enhanced_super124 self.record_id→ 1 = record_id1 #?enhanced_record_id125 self.data→ Enhanced = dataEnhanced #?enhanced_dataoutputEnhancedRecord: EnhancedRecord(1, Enhanced)def as_json(self) -> str: #?as_json_method
73def as_json(selfEnhancedRecord(1, Enhanced)) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json<module 'json' from '/usr/local/lib/python3.12/json/__init__.py'>.dumps(self.to_dict(), default=str) #?json_dumpsprint(f" as_json: {enhanced.as_json()}") #?enhanced_json
26print(f"EnhancedRecord: {enhanced}") #?print_enhanced27print(f" as_json: {enhancedEnhancedRecord(1, Enhanced).as_json()}") #?enhanced_json28print(f" created_at: {enhanced.created_at2025-01-15 10:30:00}") #?enhanced_created2930# Mixin order matters #?order_matters31print("\n--- Mixin Order (MRO) ---")3233print("class DataRecord(DictMixin, TimestampMixin, LoggingMixin):") #?print_class_def34print(f"MRO: {[c.__name__(empty) for c in DataRecord.__mro__(<class '__main__.DataRecord'>, <class '__main__.DictMixin'>, <class '__main__.TimestampMixin'>, <class '__main__.LoggingMixin'>, <class 'object'>)]}") #?print_mro3536# User with all mixins #?user_demo37print("\n--- User with Multiple Mixins ---")3839user = User(42, "alice", "alice@example.com") #?create_user40print(f"User dict: {user.to_dict()}") #?user_dictoutput as_json: {"created_at": "2025-01-15 10:30:00", "record_id": 1, "data": "Enhanced"} created_at: 2025-01-15 10:30:00 --- Mixin Order (MRO) --- class DataRecord(DictMixin, TimestampMixin, LoggingMixin): MRO: ['DataRecord', 'DictMixin', 'TimestampMixin', 'LoggingMixin', 'object'] --- User with Multiple Mixins ---def __init__(self, user_id: int, username: str, email: str): #?user_in…
135def __init__(self⟨User B⟩, user_id42: int, usernamealice: str, emailalice@example.com: str): #?user_init136 super().__init__() #?user_super137 self.user_id = user_id #?set_user_idself.user_id ← 42, self.username ← alice, self.email ← alice@example.com
39 user→ ⟨User B⟩ = User(42, "alice", "alice@example.com") #?create_user40 print(f"User dict: {user⟨User B⟩.to_dict()}") #?user_dict41 print(f"Has timestamp: {hasattr(user, 'created_at')}") #?user_has_timestamp42 user.log("User loaded from database") #?user_log4344 # Selective mixin usage #?selective45 print("\n--- Selective Mixin Usage ---")4647 # LogOnly class only has logging #?logonly_demo48 logger = LogOnly("Logger instance") #?create_logonly49 logger.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_id102 self.data = data #?set_data103 self.status = status #?set_status104105106# Comparison: without vs with mixins #?comparison_classes107108class SimpleRecord: #?simple_record109 """Record without any mixins."""110111 def __init__(self, record_id: int, data: str): #?simple_init112 self.record_id = record_id #?simple_record_id113 self.data = data #?simple_data114115 def __str__(self): #?simple_str116 return f"SimpleRecord({self.record_id}, {self.data})" #?simple_return117118119class EnhancedRecord(DictMixin, TimestampMixin): #?enhanced_record120 """Record with dict and timestamp mixins."""121122 def __init__(self, record_id: int, data: str): #?enhanced_init123 super().__init__() #?enhanced_super124 self.record_id = record_id #?enhanced_record_id125 self.data = data #?enhanced_data126127 def __str__(self): #?enhanced_str128 return f"EnhancedRecord({self.record_id}, {self.data})" #?enhanced_return129130131# User class with all mixins #?user_class132class User(DictMixin, TimestampMixin, LoggingMixin): #?user_definition133 """User with full mixin support."""134135 def __init__(self, user_id: int, username: str, email: str): #?user_init136 super().__init__() #?user_super137 self.user_id→ 42 = user_id42 #?set_user_id138 self.username→ alice = usernamealice #?set_username139 self.email→ alice@example.com = emailalice@example.com #?set_emailprint(f"User dict: {user.to_dict()}") #?user_dict
39user = User(42, "alice", "alice@example.com") #?create_user40print(f"User dict: {user⟨User B⟩.to_dict()}") #?user_dict41print(f"Has timestamp: {hasattr(user⟨User B⟩, 'created_at')}") #?user_has_timestamp42user⟨User B⟩.log("User loaded from database") #?user_logoutputUser dict: {'created_at': datetime.datetime(2025, 1, 15, 10, 30), 'user_id': 42, 'username': 'alice', 'email': 'alice@example.com'} Has timestamp: Trueself.name ← Logger instance, logger ← ⟨LogOnly C⟩
47 # LogOnly class only has logging #?logonly_demo48 logger→ ⟨LogOnly C⟩ = LogOnly("Logger instance") #?create_logonly49 logger⟨LogOnly C⟩.log("Testing selective mixin") #?logonly_log50 print(f"Has to_dict? {hasattr(logger, 'to_dict')}") #?logonly_has_dict51 print(f"Has created_at? {hasattr(logger, 'created_at')}") #?logonly_has_timestamp5253 print("\n=== Key Points ===")54 print("""55 1. Combine multiple mixins for rich functionality56 2. Each mixin adds specific capability57 3. Order in inheritance affects MRO58 4. Pick only the mixins you need59 5. Mixins should be independent (no mixin depends on another)60 """)616263# Define individual mixins #?define_mixins6465class DictMixin: #?dict_mixin66 """Mixin for dictionary conversion."""6768 def to_dict(self) -> dict: #?to_dict_method69 """Convert object to dictionary."""70 return {k: v for k, v in self.__dict__.items() #?dict_comprehension71 if not k.startswith('_')} #?skip_private7273 def as_json(self) -> str: #?as_json_method74 """Return JSON-like string representation."""75 import json #?import_json76 return json.dumps(self.to_dict(), default=str) #?json_dumps777879class TimestampMixin: #?timestamp_mixin80 """Mixin for automatic timestamps."""8182 def __init__(self, *args, **kwargs): #?timestamp_init83 super().__init__(*args, **kwargs) #?timestamp_super84 self.created_at = datetime(2025, 1, 15, 10, 30) #?set_created_at858687class LoggingMixin: #?logging_mixin88 """Mixin for logging capability."""8990 def log(self, message: str): #?log_method91 """Log a message with class name prefix."""92 print(f"[{self.__class__.__name__}] {message}") #?print_log939495# Class combining multiple mixins #?combining_mixins96class DataRecord(DictMixin, TimestampMixin, LoggingMixin): #?data_record_class97 """Data record with dict, timestamp, and logging capabilities."""9899 def __init__(self, record_id: int, data: str, status: str): #?data_record_init100 super().__init__() #?data_record_super101 self.record_id = record_id #?set_record_id102 self.data = data #?set_data103 self.status = status #?set_status104105106# Comparison: without vs with mixins #?comparison_classes107108class SimpleRecord: #?simple_record109 """Record without any mixins."""110111 def __init__(self, record_id: int, data: str): #?simple_init112 self.record_id = record_id #?simple_record_id113 self.data = data #?simple_data114115 def __str__(self): #?simple_str116 return f"SimpleRecord({self.record_id}, {self.data})" #?simple_return117118119class EnhancedRecord(DictMixin, TimestampMixin): #?enhanced_record120 """Record with dict and timestamp mixins."""121122 def __init__(self, record_id: int, data: str): #?enhanced_init123 super().__init__() #?enhanced_super124 self.record_id = record_id #?enhanced_record_id125 self.data = data #?enhanced_data126127 def __str__(self): #?enhanced_str128 return f"EnhancedRecord({self.record_id}, {self.data})" #?enhanced_return129130131# User class with all mixins #?user_class132class User(DictMixin, TimestampMixin, LoggingMixin): #?user_definition133 """User with full mixin support."""134135 def __init__(self, user_id: int, username: str, email: str): #?user_init136 super().__init__() #?user_super137 self.user_id = user_id #?set_user_id138 self.username = username #?set_username139 self.email = email #?set_email140141142# Selective mixin usage #?selective_class143class LogOnly(LoggingMixin): #?logonly_class144 """Class with only logging mixin."""145146 def __init__(self⟨LogOnly C⟩, nameLogger instance: str): #?logonly_init147 self.name→ Logger instance = nameLogger instance #?set_namemain()
150if __name__ == "__main__":151 main()
class MyClass(MixinA, MixinB, Base): - gets all mixin methods.
Mixin with super()
Cooperative mixins that chain properly.
# Using super() in Mixins
def main():
print("=== Using super() in Mixins ===\n")
# Why super() in mixins?
print("--- Why super() in Mixins? ---")
print("When mixins need to participate in __init__ chain,")
print("super() ensures all __init__ methods are called.\n")
# Without super() - broken chain
print("--- Without super() (Broken) ---")
try:
broken = BrokenExample("test")
print(f"value: {broken.value}")
print(f"initialized: {getattr(broken, 'initialized', 'MISSING')}")
print(f"timestamped: {getattr(broken, 'timestamped', 'MISSING')}")
except AttributeError as e:
print(f"Error: {e}")
# With super() - proper chain
print("\n--- With super() (Correct) ---")
correct = CorrectExample("test")
print(f"value: {correct.value}")
print(f"initialized: {correct.initialized}")
print(f"timestamped: {correct.timestamped}")
# The **kwargs pattern
print("\n--- The **kwargs Pattern ---")
print("Pass extra kwargs through super() to next class:")
print("""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.my_attr = ...
""")
# Full cooperative example
print("--- Full Cooperative Example ---")
entity = TrackedEntity(name="Widget", category="product")
print(f"Entity: name={entity.name}, category={entity.category}")
print(f" has_id: {entity.entity_id[:8]}...")
print(f" created_at: {entity.created_at}")
print(f" initialized: {entity.initialized}")
# MRO walkthrough
print("\n--- MRO Walkthrough ---")
print(f"TrackedEntity MRO: {[c.__name__ for c in TrackedEntity.__mro__]}")
print("""
Call order:
1. TrackedEntity.__init__(name="Widget", category="product")
2. → IdMixin.__init__(category="product") [name consumed]
3. → TimestampMixin.__init__() [category consumed]
4. → InitMixin.__init__()
5. → object.__init__()
""")
print("\n=== Key Points ===")
print("""
1. Always use super().__init__(**kwargs) in mixins
2. Consume your parameters, pass the rest via **kwargs
3. All __init__ methods get called in MRO order
4. Last mixin in chain should call super() too
5. This pattern enables true cooperative inheritance
""")
# Broken: Mixins without proper super()
class BrokenMixinA:
"""Mixin that DOESN'T use super()."""
def __init__(self):
self.initialized = True
# No super() call! Chain breaks here.
class BrokenMixinB:
"""Another mixin that DOESN'T use super()."""
def __init__(self):
self.timestamped = True
# No super() call!
class BrokenExample(BrokenMixinA, BrokenMixinB):
"""BrokenMixinB.__init__ never called!"""
def __init__(self, value):
super().__init__()
self.value = value
# Correct: Mixins with proper super()
class CorrectMixinA:
"""Mixin that properly uses super()."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.initialized = True
class CorrectMixinB:
"""Another mixin that properly uses super()."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.timestamped = True
class CorrectExample(CorrectMixinA, CorrectMixinB):
"""Both mixin __init__ methods get called!"""
def __init__(self, value, **kwargs):
super().__init__(**kwargs)
self.value = value
# Full cooperative inheritance example
import uuid
from datetime import datetime
class InitMixin:
"""Base mixin - ends the super() chain."""
def __init__(self, **kwargs):
super().__init__()
self.initialized = True
class TimestampMixin:
"""Adds creation timestamp."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.created_at = datetime(2025, 1, 15, 10, 30).isoformat()
class IdMixin:
"""Adds unique ID."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.entity_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, "egtry.example"))
class TrackedEntity(IdMixin, TimestampMixin, InitMixin):
"""Entity with ID, timestamp, and init tracking."""
def __init__(self, name: str, category: str, **kwargs):
super().__init__(**kwargs)
self.name = name
self.category = category
if __name__ == "__main__":
main()
"""Mixin that DOESN'T use super()."""
72class BrokenMixinA: #?broken_mixin_a73 """Mixin that DOESN'T use super()."""7475 def __init__(self): #?broken_a_init76 self.initialized = True #?set_initialized77 # No super() call! Chain breaks here.787980class BrokenMixinB: #?broken_mixin_b81 """Another mixin that DOESN'T use super()."""8283 def __init__(self): #?broken_b_init84 self.timestamped = True #?set_timestamped85 # No super() call!868788class BrokenExample(BrokenMixinA, BrokenMixinB): #?broken_example89 """BrokenMixinB.__init__ never called!"""9091 def __init__(self, value): #?broken_example_init92 super().__init__() #?broken_super93 self.value = value #?broken_value949596# Correct: Mixins with proper super() #?correct_mixins9798class CorrectMixinA: #?correct_mixin_a99 """Mixin that properly uses super()."""100101 def __init__(self, **kwargs): #?correct_a_init102 super().__init__(**kwargs) #?correct_a_super103 self.initialized = True #?correct_initialized104105106class CorrectMixinB: #?correct_mixin_b107 """Another mixin that properly uses super()."""108109 def __init__(self, **kwargs): #?correct_b_init110 super().__init__(**kwargs) #?correct_b_super111 self.timestamped = True #?correct_timestamped112113114class CorrectExample(CorrectMixinA, CorrectMixinB): #?correct_example115 """Both mixin __init__ methods get called!"""116117 def __init__(self, value, **kwargs): #?correct_example_init118 super().__init__(**kwargs) #?correct_example_super119 self.value = value #?correct_value120121122# Full cooperative inheritance example #?full_example123124import uuid #?import_uuid125from datetime import datetime #?import_datetime126127class InitMixin: #?init_mixin128 """Base mixin - ends the super() chain."""129130 def __init__(self, **kwargs): #?init_mixin_init131 super().__init__() #?init_mixin_super132 self.initialized = True #?init_mixin_attr133134135class TimestampMixin: #?timestamp_mixin136 """Adds creation timestamp."""137138 def __init__(self, **kwargs): #?timestamp_init139 super().__init__(**kwargs) #?timestamp_super140 self.created_at = datetime(2025, 1, 15, 10, 30).isoformat() #?timestamp_attr141142143class IdMixin: #?id_mixin144 """Adds unique ID."""145146 def __init__(self, **kwargs): #?id_init147 super().__init__(**kwargs) #?id_super148 self.entity_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, "egtry.example")) #?id_attr149150151class TrackedEntity(IdMixin, TimestampMixin, InitMixin): #?tracked_entity152 """Entity with ID, timestamp, and init tracking."""def main():
3def main():4 print("=== Using super() in Mixins ===\n")56 # Why super() in mixins? #?why_super7 print("--- Why super() in Mixins? ---")8 print("When mixins need to participate in __init__ chain,")9 print("super() ensures all __init__ methods are called.\n")1011 # Without super() - broken chain #?without_super12 print("--- Without super() (Broken) ---")output=== Using super() in Mixins === --- Why super() in Mixins? --- When mixins need to participate in __init__ chain, super() ensures all __init__ methods are called. --- Without super() (Broken) ---def __init__(self, value): #?broken_example_init
91def __init__(self⟨BrokenExample A⟩, valuetest): #?broken_example_init92 super().__init__() #?broken_super93 self.value = value #?broken_valueself.initialized ← True
75def __init__(self⟨BrokenExample A⟩): #?broken_a_init76 self.initialized→ True = True #?set_initialized77 # No super() call! Chain breaks here.self.value ← test, broken ← ⟨BrokenExample A⟩
14 try: #?try_broken15 broken→ ⟨BrokenExample A⟩ = BrokenExample("test") #?create_broken16 print(f"value: {broken.valuetest}") #?print_broken_value17 print(f"initialized: {getattr(broken⟨BrokenExample A⟩, 'initialized', 'MISSING')}") #?print_broken_init18 print(f"timestamped: {getattr(broken⟨BrokenExample A⟩, 'timestamped', 'MISSING')}") #?print_broken_timestamp19 except AttributeError as e: #?catch_broken20 print(f"Error: {e}") #?print_error2122 # With super() - proper chain #?with_super23 print("\n--- With super() (Correct) ---")2425 correct = CorrectExample("test") #?create_correct26 print(f"value: {correct.value}") #?print_correct_value27 print(f"initialized: {correct.initialized}") #?print_correct_init28 print(f"timestamped: {correct.timestamped}") #?print_correct_timestamp2930 # The **kwargs pattern #?kwargs_pattern31 print("\n--- The **kwargs Pattern ---")32 print("Pass extra kwargs through super() to next class:")33 print("""34 def __init__(self, **kwargs):35 super().__init__(**kwargs)36 self.my_attr = ...37 """)3839 # Full cooperative example #?cooperative_demo40 print("--- Full Cooperative Example ---")4142 entity = TrackedEntity(name="Widget", category="product") #?create_entity43 print(f"Entity: name={entity.name}, category={entity.category}") #?print_entity_attrs44 print(f" has_id: {entity.entity_id[:8]}...") #?print_entity_id45 print(f" created_at: {entity.created_at}") #?print_entity_created46 print(f" initialized: {entity.initialized}") #?print_entity_initialized4748 # MRO walkthrough #?mro_walkthrough49 print("\n--- MRO Walkthrough ---")50 print(f"TrackedEntity MRO: {[c.__name__ for c in TrackedEntity.__mro__]}") #?print_entity_mro51 print("""52 Call order:53 1. TrackedEntity.__init__(name="Widget", category="product")54 2. → IdMixin.__init__(category="product") [name consumed]55 3. → TimestampMixin.__init__() [category consumed]56 4. → InitMixin.__init__()57 5. → object.__init__()58 """)5960 print("\n=== Key Points ===")61 print("""62 1. Always use super().__init__(**kwargs) in mixins63 2. Consume your parameters, pass the rest via **kwargs64 3. All __init__ methods get called in MRO order65 4. Last mixin in chain should call super() too66 5. This pattern enables true cooperative inheritance67 """)686970# Broken: Mixins without proper super() #?broken_mixins7172class BrokenMixinA: #?broken_mixin_a73 """Mixin that DOESN'T use super()."""7475 def __init__(self): #?broken_a_init76 self.initialized = True #?set_initialized77 # No super() call! Chain breaks here.787980class BrokenMixinB: #?broken_mixin_b81 """Another mixin that DOESN'T use super()."""8283 def __init__(self): #?broken_b_init84 self.timestamped = True #?set_timestamped85 # No super() call!868788class BrokenExample(BrokenMixinA, BrokenMixinB): #?broken_example89 """BrokenMixinB.__init__ never called!"""9091 def __init__(self, value): #?broken_example_init92 super().__init__() #?broken_super93 self.value→ test = valuetest #?broken_valueoutputvalue: test initialized: True timestamped: MISSING --- With super() (Correct) ---def __init__(self, value, **kwargs): #?correct_example_init
117def __init__(self⟨CorrectExample B⟩, valuetest, **kwargs): #?correct_example_init118 super().__init__(**kwargs) #?correct_example_super119 self.value = value #?correct_valuedef __init__(self, **kwargs): #?correct_a_init
101def __init__(self⟨CorrectExample B⟩, **kwargs): #?correct_a_init102 super().__init__(**kwargs) #?correct_a_super103 self.initialized = True #?correct_initializedself.timestamped ← True, self.initialized ← True
102 super().__init__(**kwargs) #?correct_a_super103 self.initialized→ True = True #?correct_initialized104105106class CorrectMixinB: #?correct_mixin_b107 """Another mixin that properly uses super()."""108109 def __init__(self⟨CorrectExample B⟩, **kwargs): #?correct_b_init110 super().__init__(**kwargs) #?correct_b_super111 self.timestamped→ True = True #?correct_timestampedself.value ← test, correct ← ⟨CorrectExample B⟩
25 correct→ ⟨CorrectExample B⟩ = CorrectExample("test") #?create_correct26 print(f"value: {correct.valuetest}") #?print_correct_value27 print(f"initialized: {correct.initializedTrue}") #?print_correct_init28 print(f"timestamped: {correct.timestampedTrue}") #?print_correct_timestamp2930 # The **kwargs pattern #?kwargs_pattern31 print("\n--- The **kwargs Pattern ---")32 print("Pass extra kwargs through super() to next class:")33 print("""34 def __init__(self, **kwargs):35 super().__init__(**kwargs)36 self.my_attr = ...37 """)3839 # Full cooperative example #?cooperative_demo40 print("--- Full Cooperative Example ---")4142 entity = TrackedEntity(name="Widget", category="product") #?create_entity43 print(f"Entity: name={entity.name}, category={entity.category}") #?print_entity_attrs44 print(f" has_id: {entity.entity_id[:8]}...") #?print_entity_id45 print(f" created_at: {entity.created_at}") #?print_entity_created46 print(f" initialized: {entity.initialized}") #?print_entity_initialized4748 # MRO walkthrough #?mro_walkthrough49 print("\n--- MRO Walkthrough ---")50 print(f"TrackedEntity MRO: {[c.__name__ for c in TrackedEntity.__mro__]}") #?print_entity_mro51 print("""52 Call order:53 1. TrackedEntity.__init__(name="Widget", category="product")54 2. → IdMixin.__init__(category="product") [name consumed]55 3. → TimestampMixin.__init__() [category consumed]56 4. → InitMixin.__init__()57 5. → object.__init__()58 """)5960 print("\n=== Key Points ===")61 print("""62 1. Always use super().__init__(**kwargs) in mixins63 2. Consume your parameters, pass the rest via **kwargs64 3. All __init__ methods get called in MRO order65 4. Last mixin in chain should call super() too66 5. This pattern enables true cooperative inheritance67 """)686970# Broken: Mixins without proper super() #?broken_mixins7172class BrokenMixinA: #?broken_mixin_a73 """Mixin that DOESN'T use super()."""7475 def __init__(self): #?broken_a_init76 self.initialized = True #?set_initialized77 # No super() call! Chain breaks here.787980class BrokenMixinB: #?broken_mixin_b81 """Another mixin that DOESN'T use super()."""8283 def __init__(self): #?broken_b_init84 self.timestamped = True #?set_timestamped85 # No super() call!868788class BrokenExample(BrokenMixinA, BrokenMixinB): #?broken_example89 """BrokenMixinB.__init__ never called!"""9091 def __init__(self, value): #?broken_example_init92 super().__init__() #?broken_super93 self.value = value #?broken_value949596# Correct: Mixins with proper super() #?correct_mixins9798class CorrectMixinA: #?correct_mixin_a99 """Mixin that properly uses super()."""100101 def __init__(self, **kwargs): #?correct_a_init102 super().__init__(**kwargs) #?correct_a_super103 self.initialized = True #?correct_initialized104105106class CorrectMixinB: #?correct_mixin_b107 """Another mixin that properly uses super()."""108109 def __init__(self, **kwargs): #?correct_b_init110 super().__init__(**kwargs) #?correct_b_super111 self.timestamped = True #?correct_timestamped112113114class CorrectExample(CorrectMixinA, CorrectMixinB): #?correct_example115 """Both mixin __init__ methods get called!"""116117 def __init__(self, value, **kwargs): #?correct_example_init118 super().__init__(**kwargs) #?correct_example_super119 self.value→ test = valuetest #?correct_valueoutputvalue: test initialized: True timestamped: True --- The **kwargs Pattern --- Pass extra kwargs through super() to next class: def __init__(self, **kwargs): super().__init__(**kwargs) self.my_attr = ... --- Full Cooperative Example ---def __init__(self, name: str, category: str, **kwargs): #?entity_init
154def __init__(self⟨TrackedEntity C⟩, nameWidget: str, categoryproduct: str, **kwargs): #?entity_init155 super().__init__(**kwargs) #?entity_super156 self.name = name #?entity_namedef __init__(self, **kwargs): #?id_init
146def __init__(self⟨TrackedEntity C⟩, **kwargs): #?id_init147 super().__init__(**kwargs) #?id_super148 self.entity_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, "egtry.example")) #?id_attrdef __init__(self, **kwargs): #?timestamp_init
138def __init__(self⟨TrackedEntity C⟩, **kwargs): #?timestamp_init139 super().__init__(**kwargs) #?timestamp_super140 self.created_at = datetime(2025, 1, 15, 10, 30).isoformat() #?timestamp_attrself.initialized ← True
130def __init__(self⟨TrackedEntity C⟩, **kwargs): #?init_mixin_init131 super().__init__() #?init_mixin_super132 self.initialized→ True = True #?init_mixin_attrself.created_at ← 2025-01-15T10:30:00
139super().__init__(**kwargs) #?timestamp_super140self.created_at→ 2025-01-15T10:30:00 = datetime(2025, 1, 15, 10, 30).isoformat() #?timestamp_attrself.entity_id ← ⟨id D⟩
147super().__init__(**kwargs) #?id_super148self.entity_id→ ⟨id D⟩ = str(uuid<module 'uuid' from '/usr/local/lib/python3.12/uuid.py'>.uuid5(uuid.NAMESPACE_DNS⟨id E⟩, "egtry.example")) #?id_attrself.name ← Widget, self.category ← product, entity ← ⟨TrackedEntity C⟩
42 entity→ ⟨TrackedEntity C⟩ = TrackedEntity(name="Widget", category="product") #?create_entity43 print(f"Entity: name={entity.nameWidget}, category={entity.categoryproduct}") #?print_entity_attrs44 print(f" has_id: {entity.entity_id[:8]43b125c1}...") #?print_entity_id45 print(f" created_at: {entity.created_at2025-01-15T10:30:00}") #?print_entity_created46 print(f" initialized: {entity.initializedTrue}") #?print_entity_initialized4748 # MRO walkthrough #?mro_walkthrough49 print("\n--- MRO Walkthrough ---")50 print(f"TrackedEntity MRO: {[c.__name__(empty) for c in TrackedEntity.__mro__(<class '__main__.TrackedEntity'>, <class '__main__.IdMixin'>, <class '__main__.TimestampMixin'>, <class '__main__.InitMixin'>, <class 'object'>)]}") #?print_entity_mro51 print("""52 Call order:53 1. TrackedEntity.__init__(name="Widget", category="product")54 2. → IdMixin.__init__(category="product") [name consumed]55 3. → TimestampMixin.__init__() [category consumed]56 4. → InitMixin.__init__()57 5. → object.__init__()58 """)5960 print("\n=== Key Points ===")61 print("""62 1. Always use super().__init__(**kwargs) in mixins63 2. Consume your parameters, pass the rest via **kwargs64 3. All __init__ methods get called in MRO order65 4. Last mixin in chain should call super() too66 5. This pattern enables true cooperative inheritance67 """)686970# Broken: Mixins without proper super() #?broken_mixins7172class BrokenMixinA: #?broken_mixin_a73 """Mixin that DOESN'T use super()."""7475 def __init__(self): #?broken_a_init76 self.initialized = True #?set_initialized77 # No super() call! Chain breaks here.787980class BrokenMixinB: #?broken_mixin_b81 """Another mixin that DOESN'T use super()."""8283 def __init__(self): #?broken_b_init84 self.timestamped = True #?set_timestamped85 # No super() call!868788class BrokenExample(BrokenMixinA, BrokenMixinB): #?broken_example89 """BrokenMixinB.__init__ never called!"""9091 def __init__(self, value): #?broken_example_init92 super().__init__() #?broken_super93 self.value = value #?broken_value949596# Correct: Mixins with proper super() #?correct_mixins9798class CorrectMixinA: #?correct_mixin_a99 """Mixin that properly uses super()."""100101 def __init__(self, **kwargs): #?correct_a_init102 super().__init__(**kwargs) #?correct_a_super103 self.initialized = True #?correct_initialized104105106class CorrectMixinB: #?correct_mixin_b107 """Another mixin that properly uses super()."""108109 def __init__(self, **kwargs): #?correct_b_init110 super().__init__(**kwargs) #?correct_b_super111 self.timestamped = True #?correct_timestamped112113114class CorrectExample(CorrectMixinA, CorrectMixinB): #?correct_example115 """Both mixin __init__ methods get called!"""116117 def __init__(self, value, **kwargs): #?correct_example_init118 super().__init__(**kwargs) #?correct_example_super119 self.value = value #?correct_value120121122# Full cooperative inheritance example #?full_example123124import uuid #?import_uuid125from datetime import datetime #?import_datetime126127class InitMixin: #?init_mixin128 """Base mixin - ends the super() chain."""129130 def __init__(self, **kwargs): #?init_mixin_init131 super().__init__() #?init_mixin_super132 self.initialized = True #?init_mixin_attr133134135class TimestampMixin: #?timestamp_mixin136 """Adds creation timestamp."""137138 def __init__(self, **kwargs): #?timestamp_init139 super().__init__(**kwargs) #?timestamp_super140 self.created_at = datetime(2025, 1, 15, 10, 30).isoformat() #?timestamp_attr141142143class IdMixin: #?id_mixin144 """Adds unique ID."""145146 def __init__(self, **kwargs): #?id_init147 super().__init__(**kwargs) #?id_super148 self.entity_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, "egtry.example")) #?id_attr149150151class TrackedEntity(IdMixin, TimestampMixin, InitMixin): #?tracked_entity152 """Entity with ID, timestamp, and init tracking."""153154 def __init__(self, name: str, category: str, **kwargs): #?entity_init155 super().__init__(**kwargs) #?entity_super156 self.name→ Widget = nameWidget #?entity_name157 self.category→ product = categoryproduct #?entity_categoryoutputEntity: name=Widget, category=product has_id: 43b125c1... created_at: 2025-01-15T10:30:00 initialized: True --- MRO Walkthrough --- TrackedEntity MRO: ['TrackedEntity', 'IdMixin', 'TimestampMixin', 'InitMixin', 'object'] Call order: 1. TrackedEntity.__init__(name="Widget", category="product") 2. → IdMixin.__init__(category="product") [name consumed] 3. → TimestampMixin.__init__() [category consumed] 4. → InitMixin.__init__() 5. → object.__init__() === Key Points === 1. Always use super().__init__(**kwargs) in mixins 2. Consume your parameters, pass the rest via **kwargs 3. All __init__ methods get called in MRO order 4. Last mixin in chain should call super() too 5. This pattern enables true cooperative inheritancemain()
160if __name__ == "__main__":161 main()
super() ensures all mixins in chain get called.
Common mixin patterns
Serialization, comparison, logging mixins.
# Common Mixin Patterns
import json
from datetime import datetime
def main():
print("=== Common Mixin Patterns ===\n")
# 1. Serialization Mixin
print("--- 1. Serialization Mixin ---")
user = User(1, "alice", "alice@example.com")
print(f"Original: {user}")
print(f"to_dict: {user.to_dict()}")
print(f"to_json: {user.to_json()}")
# Reconstruct from dict
data = user.to_dict()
user2 = User.from_dict(data)
print(f"Reconstructed: {user2}")
# 2. Comparison Mixin
print("\n--- 2. Comparison Mixin ---")
v1 = Version(1, 0, 0)
v2 = Version(1, 2, 0)
v3 = Version(1, 0, 0)
print(f"v1 = {v1}")
print(f"v2 = {v2}")
print(f"v3 = {v3}")
print(f"v1 == v3: {v1 == v3}")
print(f"v1 < v2: {v1 < v2}")
print(f"v2 > v1: {v2 > v1}")
print(f"v1 <= v3: {v1 <= v3}")
# Sorting works too
versions = [v2, v1, v3]
print(f"Sorted: {sorted(versions)}")
# 3. Validation Mixin
print("\n--- 3. Validation Mixin ---")
product = Product("Laptop", 999.99, 10)
print(f"Valid product: {product}")
try:
invalid = Product("", -100, -5)
except ValueError as e:
print(f"Validation failed: {e}")
# 4. Repr Mixin
print("\n--- 4. Repr Mixin ---")
item = Item("Widget", 42)
print(f"repr: {item!r}")
print(f"str: {item}")
print("\n=== Common Mixin Use Cases ===")
print("""
• SerializableMixin: Convert to/from dict, JSON, XML
• ComparableMixin: Enable <, >, ==, <=, >= operators
• ValidatableMixin: Add validation methods
• ReprMixin: Auto-generate __repr__ and __str__
• HashableMixin: Make objects hashable (for sets/dicts)
• CopyableMixin: Deep/shallow copy support
""")
# 1. Serialization Mixin
class SerializableMixin:
"""Mixin for JSON serialization/deserialization."""
def to_dict(self) -> dict:
"""Convert to dictionary."""
return {k: v for k, v in self.__dict__.items()
if not k.startswith('_')}
def to_json(self) -> str:
"""Convert to JSON string."""
return json.dumps(self.to_dict(), default=str)
@classmethod
def from_dict(cls, data: dict):
"""Create instance from dictionary."""
return cls(**data)
# 2. Comparison Mixin
class ComparableMixin:
"""Mixin that enables comparison operators.
Requires: _compare_key() method in the class.
"""
def _compare_key(self):
"""Override this to define comparison key."""
raise NotImplementedError("Subclass must implement _compare_key()")
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self._compare_key() == other._compare_key()
def __lt__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self._compare_key() < other._compare_key()
def __le__(self, other):
return self == other or self < other
def __gt__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self._compare_key() > other._compare_key()
def __ge__(self, other):
return self == other or self > other
# 3. Validation Mixin
class ValidatableMixin:
"""Mixin that adds validation support."""
def validate(self):
"""Validate the object. Override _get_validations()."""
errors = []
for field, value, check, message in self._get_validations():
if not check(value):
errors.append(f"{field}: {message}")
if errors:
raise ValueError("; ".join(errors))
def _get_validations(self):
"""Return list of (field, value, check_func, error_msg)."""
return []
# 4. Repr Mixin
class ReprMixin:
"""Mixin that auto-generates __repr__ and __str__."""
def __repr__(self):
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()
if not k.startswith('_'))
return f"{self.__class__.__name__}({attrs})"
def __str__(self):
return self.__repr__()
# Classes using the mixins
class User(SerializableMixin):
"""User with serialization support."""
def __init__(self, user_id: int, username: str, email: str):
self.user_id = user_id
self.username = username
self.email = email
def __str__(self):
return f"User({self.user_id}, {self.username})"
class Version(ComparableMixin):
"""Version with comparison support."""
def __init__(self, major: int, minor: int, patch: int):
self.major = major
self.minor = minor
self.patch = patch
def _compare_key(self):
"""Comparison key: tuple of (major, minor, patch)."""
return (self.major, self.minor, self.patch)
def __repr__(self):
return f"v{self.major}.{self.minor}.{self.patch}"
class Product(ValidatableMixin):
"""Product with validation support."""
def __init__(self, name: str, price: float, quantity: int):
self.name = name
self.price = price
self.quantity = quantity
self.validate()
def _get_validations(self):
"""Define product validations."""
return [
("name", self.name, lambda x: x and len(x) > 0, "Name is required"),
("price", self.price, lambda x: x >= 0, "Price must be non-negative"),
("quantity", self.quantity, lambda x: x >= 0, "Quantity must be non-negative"),
]
def __str__(self):
return f"Product({self.name}, ${self.price}, qty={self.quantity})"
class Item(ReprMixin):
"""Item with auto-generated repr."""
def __init__(self, name: str, value: int):
self.name = name
self.value = value
if __name__ == "__main__":
main()
"""Mixin for JSON serialization/deserialization."""
72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self, user_id: int, username: str, email: str): #?user_init161 self.user_id = user_id #?set_user_id162 self.username = username #?set_username163 self.email = email #?set_email164165 def __str__(self): #?user_str166 return f"User({self.user_id}, {self.username})" #?user_str_return167168169class Version(ComparableMixin): #?version_class170 """Version with comparison support."""171172 def __init__(self, major: int, minor: int, patch: int): #?version_init173 self.major = major #?set_major174 self.minor = minor #?set_minor175 self.patch = patch #?set_patch176177 def _compare_key(self): #?version_compare_key178 """Comparison key: tuple of (major, minor, patch)."""179 return (self.major, self.minor, self.patch) #?return_version_tuple180181 def __repr__(self): #?version_repr182 return f"v{self.major}.{self.minor}.{self.patch}" #?version_repr_return183184185class Product(ValidatableMixin): #?product_class186 """Product with validation support."""187188 def __init__(self, name: str, price: float, quantity: int): #?product_init189 self.name = name #?set_name190 self.price = price #?set_price191 self.quantity = quantity #?set_quantity192 self.validate() #?call_validate193194 def _get_validations(self): #?product_validations195 """Define product validations."""196 return [ #?return_validations197 ("name", self.name, lambda x: x and len(x) > 0, "Name is required"), #?name_validation198 ("price", self.price, lambda x: x >= 0, "Price must be non-negative"), #?price_validation199 ("quantity", self.quantity, lambda x: x >= 0, "Quantity must be non-negative"), #?quantity_validation200 ]201202 def __str__(self): #?product_str203 return f"Product({self.name}, ${self.price}, qty={self.quantity})" #?product_str_return204205206class Item(ReprMixin): #?item_class207 """Item with auto-generated repr."""def main():
6def main():7 print("=== Common Mixin Patterns ===\n")89 # 1. Serialization Mixin #?serialization_pattern10 print("--- 1. Serialization Mixin ---")1112 user = User(1, "alice", "alice@example.com") #?create_user13 print(f"Original: {user}") #?print_useroutput=== Common Mixin Patterns === --- 1. Serialization Mixin ---self.user_id ← 1, self.username ← alice, self.email ← alice@example.com
pass 1 of 212 user→ User(1, alice) = User(1, "alice", "alice@example.com") #?create_user13 print(f"Original: {userUser(1, alice)}") #?print_user14 print(f"to_dict: {userUser(1, alice).to_dict()}") #?user_to_dict15 print(f"to_json: {user.to_json()}") #?user_to_json1617 # Reconstruct from dict #?reconstruct18 data = user.to_dict() #?get_dict19 user2 = User.from_dict(data) #?from_dict20 print(f"Reconstructed: {user2}") #?print_reconstructed2122 # 2. Comparison Mixin #?comparison_pattern23 print("\n--- 2. Comparison Mixin ---")2425 v1 = Version(1, 0, 0) #?create_v126 v2 = Version(1, 2, 0) #?create_v227 v3 = Version(1, 0, 0) #?create_v32829 print(f"v1 = {v1}") #?print_v130 print(f"v2 = {v2}") #?print_v231 print(f"v3 = {v3}") #?print_v33233 print(f"v1 == v3: {v1 == v3}") #?eq_check34 print(f"v1 < v2: {v1 < v2}") #?lt_check35 print(f"v2 > v1: {v2 > v1}") #?gt_check36 print(f"v1 <= v3: {v1 <= v3}") #?le_check3738 # Sorting works too #?sorting39 versions = [v2, v1, v3] #?version_list40 print(f"Sorted: {sorted(versions)}") #?sort_versions4142 # 3. Validation Mixin #?validation_pattern43 print("\n--- 3. Validation Mixin ---")4445 product = Product("Laptop", 999.99, 10) #?create_product46 print(f"Valid product: {product}") #?print_product4748 try: #?try_invalid49 invalid = Product("", -100, -5) #?create_invalid50 except ValueError as e: #?catch_invalid51 print(f"Validation failed: {e}") #?print_invalid5253 # 4. Repr Mixin #?repr_pattern54 print("\n--- 4. Repr Mixin ---")5556 item = Item("Widget", 42) #?create_item57 print(f"repr: {item!r}") #?print_repr58 print(f"str: {item}") #?print_str5960 print("\n=== Common Mixin Use Cases ===")61 print("""62 • SerializableMixin: Convert to/from dict, JSON, XML63 • ComparableMixin: Enable <, >, ==, <=, >= operators64 • ValidatableMixin: Add validation methods65 • ReprMixin: Auto-generate __repr__ and __str__66 • HashableMixin: Make objects hashable (for sets/dicts)67 • CopyableMixin: Deep/shallow copy support68 """)697071# 1. Serialization Mixin #?define_serializable72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self(empty), user_id1: int, usernamealice: str, emailalice@example.com: str): #?user_init161 self.user_id→ 1 = user_id1 #?set_user_id162 self.username→ alice = usernamealice #?set_username163 self.email→ alice@example.com = emailalice@example.com #?set_emailoutputOriginal: User(1, alice)def to_dict(self) -> dict: #?to_dict
pass 1 of 375def to_dict(selfUser(1, alice)) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k(empty): v(empty) for k, v in self.__dict__{'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}.items() #?dict_items78 if not k(empty).startswith('_')} #?skip_privateprint(f"to_dict: {user.to_dict()}") #?user_to_dict
13print(f"Original: {user}") #?print_user14print(f"to_dict: {userUser(1, alice).to_dict()}") #?user_to_dict15print(f"to_json: {userUser(1, alice).to_json()}") #?user_to_jsonoutputto_dict: {'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}def to_json(self) -> str: #?to_json
80def to_json(selfUser(1, alice)) -> str: #?to_json81 """Convert to JSON string."""82 return json<module 'json' from '/usr/local/lib/python3.12/json/__init__.py'>.dumps(self.to_dict(), default=str) #?json_dumpsprint(f"to_json: {user.to_json()}") #?user_to_json
14print(f"to_dict: {user.to_dict()}") #?user_to_dict15print(f"to_json: {userUser(1, alice).to_json()}") #?user_to_json1617# Reconstruct from dict #?reconstruct18data = userUser(1, alice).to_dict() #?get_dict19user2 = User.from_dict(data) #?from_dictoutputto_json: {"user_id": 1, "username": "alice", "email": "alice@example.com"}data ← {'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}
17# Reconstruct from dict #?reconstruct18data→ {'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'} = userUser(1, alice).to_dict() #?get_dict19user2 = User<class '__main__.User'>.from_dict(data{'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}) #?from_dict20print(f"Reconstructed: {user2}") #?print_reconstructeddef from_dict(cls, data: dict): #?from_dict_method
84@classmethod #?classmethod_decorator85def from_dict(cls<class '__main__.User'>, data{'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data{'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}) #?return_instanceself.user_id ← 1, self.username ← alice, self.email ← alice@example.com
pass 2 of 218 data = user.to_dict() #?get_dict19 user2→ User(1, alice) = User<class '__main__.User'>.from_dict(data{'user_id': 1, 'username': 'alice', 'email': 'alice@example.com'}) #?from_dict20 print(f"Reconstructed: {user2User(1, alice)}") #?print_reconstructed2122 # 2. Comparison Mixin #?comparison_pattern23 print("\n--- 2. Comparison Mixin ---")2425 v1 = Version(1, 0, 0) #?create_v126 v2 = Version(1, 2, 0) #?create_v227 v3 = Version(1, 0, 0) #?create_v32829 print(f"v1 = {v1}") #?print_v130 print(f"v2 = {v2}") #?print_v231 print(f"v3 = {v3}") #?print_v33233 print(f"v1 == v3: {v1 == v3}") #?eq_check34 print(f"v1 < v2: {v1 < v2}") #?lt_check35 print(f"v2 > v1: {v2 > v1}") #?gt_check36 print(f"v1 <= v3: {v1 <= v3}") #?le_check3738 # Sorting works too #?sorting39 versions = [v2, v1, v3] #?version_list40 print(f"Sorted: {sorted(versions)}") #?sort_versions4142 # 3. Validation Mixin #?validation_pattern43 print("\n--- 3. Validation Mixin ---")4445 product = Product("Laptop", 999.99, 10) #?create_product46 print(f"Valid product: {product}") #?print_product4748 try: #?try_invalid49 invalid = Product("", -100, -5) #?create_invalid50 except ValueError as e: #?catch_invalid51 print(f"Validation failed: {e}") #?print_invalid5253 # 4. Repr Mixin #?repr_pattern54 print("\n--- 4. Repr Mixin ---")5556 item = Item("Widget", 42) #?create_item57 print(f"repr: {item!r}") #?print_repr58 print(f"str: {item}") #?print_str5960 print("\n=== Common Mixin Use Cases ===")61 print("""62 • SerializableMixin: Convert to/from dict, JSON, XML63 • ComparableMixin: Enable <, >, ==, <=, >= operators64 • ValidatableMixin: Add validation methods65 • ReprMixin: Auto-generate __repr__ and __str__66 • HashableMixin: Make objects hashable (for sets/dicts)67 • CopyableMixin: Deep/shallow copy support68 """)697071# 1. Serialization Mixin #?define_serializable72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self(empty), user_id1: int, usernamealice: str, emailalice@example.com: str): #?user_init161 self.user_id→ 1 = user_id1 #?set_user_id162 self.username→ alice = usernamealice #?set_username163 self.email→ alice@example.com = emailalice@example.com #?set_emailoutputReconstructed: User(1, alice) --- 2. Comparison Mixin ---self.major ← 1, self.minor ← 0, self.patch ← 0, v1 ← v1.0.0
pass 1 of 325 v1→ v1.0.0 = Version(1, 0, 0) #?create_v126 v2 = Version(1, 2, 0) #?create_v227 v3 = Version(1, 0, 0) #?create_v32829 print(f"v1 = {v1}") #?print_v130 print(f"v2 = {v2}") #?print_v231 print(f"v3 = {v3}") #?print_v33233 print(f"v1 == v3: {v1 == v3}") #?eq_check34 print(f"v1 < v2: {v1 < v2}") #?lt_check35 print(f"v2 > v1: {v2 > v1}") #?gt_check36 print(f"v1 <= v3: {v1 <= v3}") #?le_check3738 # Sorting works too #?sorting39 versions = [v2, v1, v3] #?version_list40 print(f"Sorted: {sorted(versions)}") #?sort_versions4142 # 3. Validation Mixin #?validation_pattern43 print("\n--- 3. Validation Mixin ---")4445 product = Product("Laptop", 999.99, 10) #?create_product46 print(f"Valid product: {product}") #?print_product4748 try: #?try_invalid49 invalid = Product("", -100, -5) #?create_invalid50 except ValueError as e: #?catch_invalid51 print(f"Validation failed: {e}") #?print_invalid5253 # 4. Repr Mixin #?repr_pattern54 print("\n--- 4. Repr Mixin ---")5556 item = Item("Widget", 42) #?create_item57 print(f"repr: {item!r}") #?print_repr58 print(f"str: {item}") #?print_str5960 print("\n=== Common Mixin Use Cases ===")61 print("""62 • SerializableMixin: Convert to/from dict, JSON, XML63 • ComparableMixin: Enable <, >, ==, <=, >= operators64 • ValidatableMixin: Add validation methods65 • ReprMixin: Auto-generate __repr__ and __str__66 • HashableMixin: Make objects hashable (for sets/dicts)67 • CopyableMixin: Deep/shallow copy support68 """)697071# 1. Serialization Mixin #?define_serializable72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self, user_id: int, username: str, email: str): #?user_init161 self.user_id = user_id #?set_user_id162 self.username = username #?set_username163 self.email = email #?set_email164165 def __str__(self): #?user_str166 return f"User({self.user_id}, {self.username})" #?user_str_return167168169class Version(ComparableMixin): #?version_class170 """Version with comparison support."""171172 def __init__(self(empty), major1: int, minor0: int, patch0: int): #?version_init173 self.major→ 1 = major1 #?set_major174 self.minor→ 0 = minor0 #?set_minor175 self.patch→ 0 = patch0 #?set_patchAll 3 passes — pass 1 is the card above pass minorotherself.majorself.minorself.patchv1v2v31 0 — 1 0 0 v1.0.0 — — 2 2 — 1 2 0 — v1.2.0 — 3 0 v1.0.0 1 0 0 v1.0.0 v1.2.0 v1.0.0 def __eq__(self, other): #?eq_method
pass 1 of 2101def __eq__(selfv1.0.0, otherv1.0.0): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == otherv1.0.0._compare_key() #?compare_eqdef _compare_key(self): #?version_compare_key
pass 1 of 16177def _compare_key(selfv1.0.0): #?version_compare_key178 """Comparison key: tuple of (major, minor, patch)."""179 return (self.major1, self.minor0, self.patch0) #?return_version_tuple16 passes — pass 1 is the card above pass selfself.minor1 v1.0.0 0 2 v1.0.0 0 3 v1.0.0 0 4 v1.2.0 2 5 v1.2.0 2 6 v1.0.0 0 7 v1.0.0 0 8 v1.0.0 0 9 v1.0.0 0 ⋯ 5 more passes ⋯ 15 v1.0.0 0 16 v1.0.0 0 print(f"v1 == v3: {v1 == v3}") #?eq_check
33print(f"v1 == v3: {v1v1.0.0 == v3v1.0.0}") #?eq_check34print(f"v1 < v2: {v1v1.0.0 < v2v1.2.0}") #?lt_check35print(f"v2 > v1: {v2 > v1}") #?gt_checkoutputv1 == v3: Truedef __lt__(self, other): #?lt_method
pass 1 of 5106def __lt__(selfv1.0.0, otherv1.2.0): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < otherv1.2.0._compare_key() #?compare_ltAll 5 passes — pass 1 is the card above pass other1 v1.2.0 2 v1.2.0 3 v1.0.0 4 v1.2.0 5 v1.0.0 print(f"v1 < v2: {v1 < v2}") #?lt_check
33print(f"v1 == v3: {v1 == v3}") #?eq_check34print(f"v1 < v2: {v1v1.0.0 < v2v1.2.0}") #?lt_check35print(f"v2 > v1: {v2v1.2.0 > v1v1.0.0}") #?gt_check36print(f"v1 <= v3: {v1 <= v3}") #?le_checkoutputv1 < v2: Truedef __gt__(self, other): #?gt_method
114def __gt__(selfv1.2.0, otherv1.0.0): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > otherv1.0.0._compare_key() #?compare_gtprint(f"v2 > v1: {v2 > v1}") #?gt_check
34print(f"v1 < v2: {v1 < v2}") #?lt_check35print(f"v2 > v1: {v2v1.2.0 > v1v1.0.0}") #?gt_check36print(f"v1 <= v3: {v1v1.0.0 <= v3v1.0.0}") #?le_checkoutputv2 > v1: Truedef __le__(self, other): #?le_method
111def __le__(selfv1.0.0, otherv1.0.0): #?le_method112 return self == otherv1.0.0 or self < other #?compare_ledef __eq__(self, other): #?eq_method
pass 2 of 2101def __eq__(selfv1.0.0, otherv1.0.0): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == otherv1.0.0._compare_key() #?compare_eqversions ← [v1.2.0, v1.0.0, v1.0.0]
35print(f"v2 > v1: {v2 > v1}") #?gt_check36print(f"v1 <= v3: {v1v1.0.0 <= v3v1.0.0}") #?le_check3738# Sorting works too #?sorting39versions→ [v1.2.0, v1.0.0, v1.0.0] = [v2v1.2.0, v1v1.0.0, v3v1.0.0] #?version_list40print(f"Sorted: {sorted(versions[v1.2.0, v1.0.0, v1.0.0])}") #?sort_versionsoutputv1 <= v3: Trueprint(f"Sorted: {sorted(versions)}") #?sort_versions
39versions = [v2, v1, v3] #?version_list40print(f"Sorted: {sorted(versions[v1.2.0, v1.0.0, v1.0.0])}") #?sort_versions4142# 3. Validation Mixin #?validation_pattern43print("\n--- 3. Validation Mixin ---")4445product = Product("Laptop", 999.99, 10) #?create_product46print(f"Valid product: {product}") #?print_productoutputSorted: [v1.0.0, v1.0.0, v1.2.0] --- 3. Validation Mixin ---self.name ← Laptop, self.price ← 999.99, self.quantity ← 10
pass 1 of 2188def __init__(self(empty), nameLaptop: str, price999.99: float, quantity10: int): #?product_init189 self.name→ Laptop = nameLaptop #?set_name190 self.price→ 999.99 = price999.99 #?set_price191 self.quantity→ 10 = quantity10 #?set_quantity192 self.validate() #?call_validateerrors ← []
pass 1 of 2127def validate(selfProduct(Laptop, $999.99, qty=10)): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors→ [] = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validationsdef _get_validations(self): #?product_validations
pass 1 of 2194def _get_validations(selfProduct(Laptop, $999.99, qty=10)): #?product_validations195 """Define product validations."""196 return [ #?return_validations197 ("name", self.nameLaptop, lambda x: x and len(x) > 0, "Name is required"), #?name_validation198 ("price", self.price999.99, lambda x: x >= 0, "Price must be non-negative"), #?price_validation199 ("quantity", self.quantity10, lambda x: x >= 0, "Quantity must be non-negative"), #?quantity_validation200 ]for field, value, check, message in self._get_validations(): #?loop_va…
pass 1 of 6129errors = [] #?errors_list130for fieldname, valueLaptop, check<function Product._get_validations.<locals>.<lambda> at ⟨addr A⟩>, messageName is required in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_errorAll 6 passes — pass 1 is the card above pass fieldvaluecheckmessageerrorse1 name Laptop <function Product._get_validations.<locals>.<lambda> at ⟨addr A⟩> Name is required — — 2 price 999.99 <function Product._get_validations.<locals>.<lambda> at ⟨addr B⟩> Price must be non-negative — — 3 quantity 10 <function Product._get_validations.<locals>.<lambda> at ⟨addr C⟩> Quantity must be non-negative — — 4 name (empty) <function Product._get_validations.<locals>.<lambda> at ⟨addr D⟩> Name is required — — 5 price -100 <function Product._get_validations.<locals>.<lambda> at ⟨addr E⟩> Price must be non-negative — — 6 quantity -5 <function Product._get_validations.<locals>.<lambda> at ⟨addr F⟩> Quantity must be non-negative ['name: Name is required', 'price: Price must be non-negative', 'quantity: Quantity must be non-negative'] name: Name is required; price: Price must be non-negative; quantity: Quantity must be non-negative product ← Product(Laptop, $999.99, qty=10)
45 product→ Product(Laptop, $999.99, qty=10) = Product("Laptop", 999.99, 10) #?create_product46 print(f"Valid product: {productProduct(Laptop, $999.99, qty=10)}") #?print_product4748 try: #?try_invalid49 invalid = Product("", -100, -5) #?create_invalid50 except ValueError as e: #?catch_invalid51 print(f"Validation failed: {e}") #?print_invalid5253 # 4. Repr Mixin #?repr_pattern54 print("\n--- 4. Repr Mixin ---")5556 item = Item("Widget", 42) #?create_item57 print(f"repr: {item!r}") #?print_repr58 print(f"str: {item}") #?print_str5960 print("\n=== Common Mixin Use Cases ===")61 print("""62 • SerializableMixin: Convert to/from dict, JSON, XML63 • ComparableMixin: Enable <, >, ==, <=, >= operators64 • ValidatableMixin: Add validation methods65 • ReprMixin: Auto-generate __repr__ and __str__66 • HashableMixin: Make objects hashable (for sets/dicts)67 • CopyableMixin: Deep/shallow copy support68 """)697071# 1. Serialization Mixin #?define_serializable72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self, user_id: int, username: str, email: str): #?user_init161 self.user_id = user_id #?set_user_id162 self.username = username #?set_username163 self.email = email #?set_email164165 def __str__(self): #?user_str166 return f"User({self.user_id}, {self.username})" #?user_str_return167168169class Version(ComparableMixin): #?version_class170 """Version with comparison support."""171172 def __init__(self, major: int, minor: int, patch: int): #?version_init173 self.major = major #?set_major174 self.minor = minor #?set_minor175 self.patch = patch #?set_patch176177 def _compare_key(self): #?version_compare_key178 """Comparison key: tuple of (major, minor, patch)."""179 return (self.major, self.minor, self.patch) #?return_version_tuple180181 def __repr__(self): #?version_repr182 return f"v{self.major}.{self.minor}.{self.patch}" #?version_repr_return183184185class Product(ValidatableMixin): #?product_class186 """Product with validation support."""187188 def __init__(self, name: str, price: float, quantity: int): #?product_init189 self.name = name #?set_name190 self.price = price #?set_price191 self.quantity = quantity #?set_quantity192 self.validate() #?call_validateoutputValid product: Product(Laptop, $999.99, qty=10)self.name ← (empty), self.price ← -100, self.quantity ← -5
pass 2 of 2188def __init__(self(empty), name(empty): str, price-100: float, quantity-5: int): #?product_init189 self.name→ (empty) = name(empty) #?set_name190 self.price→ -100 = price-100 #?set_price191 self.quantity→ -5 = quantity-5 #?set_quantity192 self.validate() #?call_validateerrors ← []
pass 2 of 2127def validate(selfProduct(, $-100, qty=-5)): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors→ [] = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validationsdef _get_validations(self): #?product_validations
pass 2 of 2194def _get_validations(selfProduct(, $-100, qty=-5)): #?product_validations195 """Define product validations."""196 return [ #?return_validations197 ("name", self.name(empty), lambda x: x and len(x) > 0, "Name is required"), #?name_validation198 ("price", self.price-100, lambda x: x >= 0, "Price must be non-negative"), #?price_validation199 ("quantity", self.quantity-5, lambda x: x >= 0, "Quantity must be non-negative"), #?quantity_validation200 ]errors ← ['name: Name is required']
pass 1 of 3130for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value(empty)): #?check_validation132 errors→ ['name: Name is required'].append(f"{fieldname}: {messageName is required}") #?append_errorAll 3 passes — pass 1 is the card above pass valuefieldmessageeerrors1 (empty) name Name is required — [] → ['name: Name is required'] 2 -100 price Price must be non-negative — ['name: Name is required'] → ['name: Name is required', 'price: Price must be non-negative'] 3 -5 quantity Quantity must be non-negative name: Name is required; price: Price must be non-negative; quantity: Quantity must be non-negative ['name: Name is required', 'price: Price must be non-negative'] → ['name: Name is required', 'price: Price must be non-negative', 'quantity: Quantity must be non-negative'] if errors: #?if_errors
134if errors['name: Name is required', 'price: Price must be non-negative', 'quantity: Quantity must be non-negative']: #?if_errors135 raise ValueError("; ".join(errors['name: Name is required', 'price: Price must be non-negative', 'quantity: Quantity must be non-negative'])) #?raise_errorsexcept ValueError as e: #?catch_invalid
49 invalid = Product("", -100, -5) #?create_invalid50except ValueError as e: #?catch_invalid51 print(f"Validation failed: {ename: Name is required; price: Price must be non-negative; quantity: Quantity must be non-negative}") #?print_invalid5253# 4. Repr Mixin #?repr_patternoutputValidation failed: name: Name is required; price: Price must be non-negative; quantity: Quantity must be non-negative Validation failed: name: Name is required; price: Price must be non-negative; quantity: Quantity must be non-negativeprint(" --- 4. Repr Mixin ---")
53# 4. Repr Mixin #?repr_pattern54print("\n--- 4. Repr Mixin ---")5556item = Item("Widget", 42) #?create_item57print(f"repr: {item!r}") #?print_reproutput --- 4. Repr Mixin ---self.name ← Widget, self.value ← 42, item ← Item(name='Widget', value=42)
56 item→ Item(name='Widget', value=42) = Item("Widget", 42) #?create_item57 print(f"repr: {itemItem(name='Widget', value=42)!r}") #?print_repr58 print(f"str: {itemItem(name='Widget', value=42)}") #?print_str5960 print("\n=== Common Mixin Use Cases ===")61 print("""62 • SerializableMixin: Convert to/from dict, JSON, XML63 • ComparableMixin: Enable <, >, ==, <=, >= operators64 • ValidatableMixin: Add validation methods65 • ReprMixin: Auto-generate __repr__ and __str__66 • HashableMixin: Make objects hashable (for sets/dicts)67 • CopyableMixin: Deep/shallow copy support68 """)697071# 1. Serialization Mixin #?define_serializable72class SerializableMixin: #?serializable_mixin73 """Mixin for JSON serialization/deserialization."""7475 def to_dict(self) -> dict: #?to_dict76 """Convert to dictionary."""77 return {k: v for k, v in self.__dict__.items() #?dict_items78 if not k.startswith('_')} #?skip_private7980 def to_json(self) -> str: #?to_json81 """Convert to JSON string."""82 return json.dumps(self.to_dict(), default=str) #?json_dumps8384 @classmethod #?classmethod_decorator85 def from_dict(cls, data: dict): #?from_dict_method86 """Create instance from dictionary."""87 return cls(**data) #?return_instance888990# 2. Comparison Mixin #?define_comparable91class ComparableMixin: #?comparable_mixin92 """Mixin that enables comparison operators.9394 Requires: _compare_key() method in the class.95 """9697 def _compare_key(self): #?compare_key98 """Override this to define comparison key."""99 raise NotImplementedError("Subclass must implement _compare_key()") #?not_implemented100101 def __eq__(self, other): #?eq_method102 if not isinstance(other, self.__class__): #?check_type_eq103 return NotImplemented #?return_not_impl104 return self._compare_key() == other._compare_key() #?compare_eq105106 def __lt__(self, other): #?lt_method107 if not isinstance(other, self.__class__): #?check_type_lt108 return NotImplemented #?return_not_impl_lt109 return self._compare_key() < other._compare_key() #?compare_lt110111 def __le__(self, other): #?le_method112 return self == other or self < other #?compare_le113114 def __gt__(self, other): #?gt_method115 if not isinstance(other, self.__class__): #?check_type_gt116 return NotImplemented #?return_not_impl_gt117 return self._compare_key() > other._compare_key() #?compare_gt118119 def __ge__(self, other): #?ge_method120 return self == other or self > other #?compare_ge121122123# 3. Validation Mixin #?define_validatable124class ValidatableMixin: #?validatable_mixin125 """Mixin that adds validation support."""126127 def validate(self): #?validate_method128 """Validate the object. Override _get_validations()."""129 errors = [] #?errors_list130 for field, value, check, message in self._get_validations(): #?loop_validations131 if not check(value): #?check_validation132 errors.append(f"{field}: {message}") #?append_error133134 if errors: #?if_errors135 raise ValueError("; ".join(errors)) #?raise_errors136137 def _get_validations(self): #?get_validations138 """Return list of (field, value, check_func, error_msg)."""139 return [] #?return_empty140141142# 4. Repr Mixin #?define_repr143class ReprMixin: #?repr_mixin144 """Mixin that auto-generates __repr__ and __str__."""145146 def __repr__(self): #?repr_method147 attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items() #?format_attrs148 if not k.startswith('_')) #?skip_private_repr149 return f"{self.__class__.__name__}({attrs})" #?return_repr150151 def __str__(self): #?str_method152 return self.__repr__() #?return_str153154155# Classes using the mixins #?using_mixins156157class User(SerializableMixin): #?user_class158 """User with serialization support."""159160 def __init__(self, user_id: int, username: str, email: str): #?user_init161 self.user_id = user_id #?set_user_id162 self.username = username #?set_username163 self.email = email #?set_email164165 def __str__(self): #?user_str166 return f"User({self.user_id}, {self.username})" #?user_str_return167168169class Version(ComparableMixin): #?version_class170 """Version with comparison support."""171172 def __init__(self, major: int, minor: int, patch: int): #?version_init173 self.major = major #?set_major174 self.minor = minor #?set_minor175 self.patch = patch #?set_patch176177 def _compare_key(self): #?version_compare_key178 """Comparison key: tuple of (major, minor, patch)."""179 return (self.major, self.minor, self.patch) #?return_version_tuple180181 def __repr__(self): #?version_repr182 return f"v{self.major}.{self.minor}.{self.patch}" #?version_repr_return183184185class Product(ValidatableMixin): #?product_class186 """Product with validation support."""187188 def __init__(self, name: str, price: float, quantity: int): #?product_init189 self.name = name #?set_name190 self.price = price #?set_price191 self.quantity = quantity #?set_quantity192 self.validate() #?call_validate193194 def _get_validations(self): #?product_validations195 """Define product validations."""196 return [ #?return_validations197 ("name", self.name, lambda x: x and len(x) > 0, "Name is required"), #?name_validation198 ("price", self.price, lambda x: x >= 0, "Price must be non-negative"), #?price_validation199 ("quantity", self.quantity, lambda x: x >= 0, "Quantity must be non-negative"), #?quantity_validation200 ]201202 def __str__(self): #?product_str203 return f"Product({self.name}, ${self.price}, qty={self.quantity})" #?product_str_return204205206class Item(ReprMixin): #?item_class207 """Item with auto-generated repr."""208209 def __init__(selfItem(), nameWidget: str, value42: int): #?item_init210 self.name→ Widget = nameWidget #?item_name211 self.value→ 42 = value42 #?item_valueoutputrepr: Item(name='Widget', value=42) str: Item(name='Widget', value=42) === Common Mixin Use Cases === • SerializableMixin: Convert to/from dict, JSON, XML • ComparableMixin: Enable <, >, ==, <=, >= operators • ValidatableMixin: Add validation methods • ReprMixin: Auto-generate __repr__ and __str__ • HashableMixin: Make objects hashable (for sets/dicts) • CopyableMixin: Deep/shallow copy supportmain()
214if __name__ == "__main__":215 main()
Popular patterns: JsonMixin, ComparableMixin, LoggingMixin.
Mixin vs inheritance
When to use each approach.
# Mixin vs Regular Inheritance
def main():
print("=== Mixin vs Regular Inheritance ===\n")
# When to use regular inheritance
print("--- When to Use Regular Inheritance ---")
print("Use when: IS-A relationship exists")
print("Example: Dog IS-A Animal\n")
dog = Dog("Buddy")
print(f"{dog.name} says: ", end="")
dog.speak()
dog.move()
# When to use mixins
print("\n--- When to Use Mixins ---")
print("Use when: Adding CAPABILITY (HAS-A behavior)")
print("Example: Dog HAS logging capability\n")
logged_dog = LoggedDog("Max")
logged_dog.log("Dog created")
logged_dog.speak()
# Comparison: Same behavior, different approaches
print("\n--- Comparison: Two Approaches ---")
print("Goal: Add serialization to multiple unrelated classes\n")
# Approach 1: Base class (problematic)
print("Approach 1: Shared Base Class")
print(" class User(SerializableBase): ...")
print(" class Product(SerializableBase): ...")
print(" Problem: What if User already has a base class?")
print(" Problem: SerializableBase isn't really a 'parent'\n")
# Approach 2: Mixin (better)
print("Approach 2: Mixin")
print(" class User(UserBase, SerializableMixin): ...")
print(" class Product(ProductBase, SerializableMixin): ...")
print(" Benefit: Can add to any class hierarchy")
print(" Benefit: Clear that it's adding capability, not identity\n")
# Demonstrate with real classes
print("--- Real Example ---")
user = User("alice", "alice@example.com")
product = Product("Laptop", 999.99)
print(f"User: {user.get_name()}")
print(f"User serialized: {user.to_dict()}")
print(f"Product: {product.get_name()}")
print(f"Product serialized: {product.to_dict()}")
# Decision guide
print("\n=== Decision Guide ===")
print("""
Use REGULAR INHERITANCE when:
┌─────────────────────────────────────────────────┐
│ • Clear IS-A relationship (Dog IS-A Animal) │
│ • Shared state and behavior │
│ • Objects are naturally in same hierarchy │
│ • Want to override parent methods │
└─────────────────────────────────────────────────┘
Use MIXIN when:
┌─────────────────────────────────────────────────┐
│ • Adding capability (HAS-A behavior) │
│ • Unrelated classes need same feature │
│ • Small, focused functionality │
│ • No shared identity/state │
│ • Want to compose behaviors flexibly │
└─────────────────────────────────────────────────┘
""")
# Anti-patterns
print("=== Anti-Patterns to Avoid ===")
print("""
✗ Mixin with complex state (use regular class)
✗ Mixin that depends on other mixins (order issues)
✗ Too many mixins (hard to understand)
✗ Using inheritance just for code reuse
✗ Deep inheritance hierarchies
""")
# Regular Inheritance Example
class Animal:
"""Base class - defines what an animal IS."""
def __init__(self, name: str):
self.name = name
def speak(self):
"""Override in subclass."""
print("Some sound")
def move(self):
"""Common to all animals."""
print(f"{self.name} is moving")
class Dog(Animal):
"""Dog IS-A Animal - clear inheritance."""
def speak(self):
print("Woof!")
# Mixin Example
class LoggingMixin:
"""Adds logging CAPABILITY."""
def log(self, message: str):
print(f"[{self.__class__.__name__}] {message}")
class LoggedDog(Animal, LoggingMixin):
"""Dog with logging capability added."""
def speak(self):
self.log("About to bark")
print("Woof!")
# Comparison: Adding serialization
class SerializableMixin:
"""Mixin - adds serialization CAPABILITY."""
def to_dict(self) -> dict:
return {k: v for k, v in self.__dict__.items()
if not k.startswith('_')}
# Base classes representing different domains
class Entity:
"""Base for database entities."""
def __init__(self):
self._id = None
def get_name(self) -> str:
raise NotImplementedError
class Item:
"""Base for store items."""
def __init__(self):
self._sku = None
def get_name(self) -> str:
raise NotImplementedError
# Classes using mixin with their own base classes
class User(Entity, SerializableMixin):
"""User IS-A Entity, HAS serialization."""
def __init__(self, username: str, email: str):
super().__init__()
self.username = username
self.email = email
def get_name(self) -> str:
return self.username
class Product(Item, SerializableMixin):
"""Product IS-A Item, HAS serialization."""
def __init__(self, name: str, price: float):
super().__init__()
self.name = name
self.price = price
def get_name(self) -> str:
return self.name
if __name__ == "__main__":
main()
"""Base class - defines what an animal IS."""
89class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self, message: str): #?log_method117 print(f"[{self.__class__.__name__}] {message}") #?print_log118119120class LoggedDog(Animal, LoggingMixin): #?logged_dog121 """Dog with logging capability added."""122123 def speak(self): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?bark126127128# Comparison: Adding serialization #?serialization_comparison129130class SerializableMixin: #?serializable_mixin131 """Mixin - adds serialization CAPABILITY."""132133 def to_dict(self) -> dict: #?to_dict134 return {k: v for k, v in self.__dict__.items() #?dict_items135 if not k.startswith('_')} #?skip_private136137138# Base classes representing different domains #?domain_bases139140class Entity: #?entity_class141 """Base for database entities."""142143 def __init__(self): #?entity_init144 self._id = None #?entity_id145146 def get_name(self) -> str: #?get_name_entity147 raise NotImplementedError #?not_implemented148149150class Item: #?item_class151 """Base for store items."""152153 def __init__(self): #?item_init154 self._sku = None #?item_sku155156 def get_name(self) -> str: #?get_name_item157 raise NotImplementedError #?not_implemented_item158159160# Classes using mixin with their own base classes #?using_mixin_with_base161162class User(Entity, SerializableMixin): #?user_class163 """User IS-A Entity, HAS serialization."""164165 def __init__(self, username: str, email: str): #?user_init166 super().__init__() #?user_super167 self.username = username #?set_username168 self.email = email #?set_email169170 def get_name(self) -> str: #?user_get_name171 return self.username #?return_username172173174class Product(Item, SerializableMixin): #?product_class175 """Product IS-A Item, HAS serialization."""def main():
3def main():4 print("=== Mixin vs Regular Inheritance ===\n")56 # When to use regular inheritance #?when_regular7 print("--- When to Use Regular Inheritance ---")8 print("Use when: IS-A relationship exists")9 print("Example: Dog IS-A Animal\n")1011 dog = Dog("Buddy") #?create_dog12 print(f"{dog.name} says: ", end="") #?dog_nameoutput=== Mixin vs Regular Inheritance === --- When to Use Regular Inheritance --- Use when: IS-A relationship exists Example: Dog IS-A Animalself.name ← Buddy, dog ← ⟨Dog A⟩
pass 1 of 211 dog→ ⟨Dog A⟩ = Dog("Buddy") #?create_dog12 print(f"{dog.nameBuddy} says: ", end="") #?dog_name13 dog⟨Dog A⟩.speak() #?dog_speak14 dog.move() #?dog_move1516 # When to use mixins #?when_mixin17 print("\n--- When to Use Mixins ---")18 print("Use when: Adding CAPABILITY (HAS-A behavior)")19 print("Example: Dog HAS logging capability\n")2021 logged_dog = LoggedDog("Max") #?create_logged_dog22 logged_dog.log("Dog created") #?logged_dog_log23 logged_dog.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self⟨Dog A⟩, nameBuddy: str): #?animal_init93 self.name→ Buddy = nameBuddy #?animal_nameoutputBuddy says:def speak(self): #?dog_speak_method
12 print(f"{dog.name} says: ", end="") #?dog_name13 dog⟨Dog A⟩.speak() #?dog_speak14 dog⟨Dog A⟩.move() #?dog_move1516 # When to use mixins #?when_mixin17 print("\n--- When to Use Mixins ---")18 print("Use when: Adding CAPABILITY (HAS-A behavior)")19 print("Example: Dog HAS logging capability\n")2021 logged_dog = LoggedDog("Max") #?create_logged_dog22 logged_dog.log("Dog created") #?logged_dog_log23 logged_dog.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self⟨Dog A⟩): #?dog_speak_method108 print("Woof!") #?woofoutputWoof!def move(self): #?animal_move
13 dog.speak() #?dog_speak14 dog⟨Dog A⟩.move() #?dog_move1516 # When to use mixins #?when_mixin17 print("\n--- When to Use Mixins ---")18 print("Use when: Adding CAPABILITY (HAS-A behavior)")19 print("Example: Dog HAS logging capability\n")2021 logged_dog = LoggedDog("Max") #?create_logged_dog22 logged_dog.log("Dog created") #?logged_dog_log23 logged_dog.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self⟨Dog A⟩): #?animal_move100 """Common to all animals."""101 print(f"{self.nameBuddy} is moving") #?print_movingoutputBuddy is moving --- When to Use Mixins --- Use when: Adding CAPABILITY (HAS-A behavior) Example: Dog HAS logging capabilityself.name ← Max, logged_dog ← ⟨LoggedDog B⟩
pass 2 of 221 logged_dog→ ⟨LoggedDog B⟩ = LoggedDog("Max") #?create_logged_dog22 logged_dog⟨LoggedDog B⟩.log("Dog created") #?logged_dog_log23 logged_dog.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self⟨LoggedDog B⟩, nameMax: str): #?animal_init93 self.name→ Max = nameMax #?animal_namedef log(self, message: str): #?log_method
pass 1 of 221 logged_dog = LoggedDog("Max") #?create_logged_dog22 logged_dog⟨LoggedDog B⟩.log("Dog created") #?logged_dog_log23 logged_dog⟨LoggedDog B⟩.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self⟨LoggedDog B⟩, messageDog created: str): #?log_method117 print(f"[{self.__class__.__name__LoggedDog}] {messageDog created}") #?print_logoutput[LoggedDog] Dog createddef speak(self): #?logged_dog_speak
123def speak(self⟨LoggedDog B⟩): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?barkdef log(self, message: str): #?log_method
pass 2 of 2116def log(self⟨LoggedDog B⟩, messageAbout to bark: str): #?log_method117 print(f"[{self.__class__.__name__LoggedDog}] {messageAbout to bark}") #?print_logoutput[LoggedDog] About to barklogged_dog.speak() #?logged_dog_speak
22 logged_dog.log("Dog created") #?logged_dog_log23 logged_dog⟨LoggedDog B⟩.speak() #?logged_dog_speak2425 # Comparison: Same behavior, different approaches #?comparison26 print("\n--- Comparison: Two Approaches ---")27 print("Goal: Add serialization to multiple unrelated classes\n")2829 # Approach 1: Base class (problematic) #?approach130 print("Approach 1: Shared Base Class")31 print(" class User(SerializableBase): ...")32 print(" class Product(SerializableBase): ...")33 print(" Problem: What if User already has a base class?")34 print(" Problem: SerializableBase isn't really a 'parent'\n")3536 # Approach 2: Mixin (better) #?approach237 print("Approach 2: Mixin")38 print(" class User(UserBase, SerializableMixin): ...")39 print(" class Product(ProductBase, SerializableMixin): ...")40 print(" Benefit: Can add to any class hierarchy")41 print(" Benefit: Clear that it's adding capability, not identity\n")4243 # Demonstrate with real classes #?demonstrate44 print("--- Real Example ---")4546 user = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self, message: str): #?log_method117 print(f"[{self.__class__.__name__}] {message}") #?print_log118119120class LoggedDog(Animal, LoggingMixin): #?logged_dog121 """Dog with logging capability added."""122123 def speak(self): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?barkoutputWoof! --- Comparison: Two Approaches --- Goal: Add serialization to multiple unrelated classes Approach 1: Shared Base Class class User(SerializableBase): ... class Product(SerializableBase): ... Problem: What if User already has a base class? Problem: SerializableBase isn't really a 'parent' Approach 2: Mixin class User(UserBase, SerializableMixin): ... class Product(ProductBase, SerializableMixin): ... Benefit: Can add to any class hierarchy Benefit: Clear that it's adding capability, not identity --- Real Example ---def __init__(self, username: str, email: str): #?user_init
165def __init__(self⟨User C⟩, usernamealice: str, emailalice@example.com: str): #?user_init166 super().__init__() #?user_super167 self.username = username #?set_usernameself._id ← None
143def __init__(self⟨User C⟩): #?entity_init144 self._id→ None = None #?entity_idself.username ← alice, self.email ← alice@example.com, user ← ⟨User C⟩
46 user→ ⟨User C⟩ = User("alice", "alice@example.com") #?create_user47 product = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self, message: str): #?log_method117 print(f"[{self.__class__.__name__}] {message}") #?print_log118119120class LoggedDog(Animal, LoggingMixin): #?logged_dog121 """Dog with logging capability added."""122123 def speak(self): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?bark126127128# Comparison: Adding serialization #?serialization_comparison129130class SerializableMixin: #?serializable_mixin131 """Mixin - adds serialization CAPABILITY."""132133 def to_dict(self) -> dict: #?to_dict134 return {k: v for k, v in self.__dict__.items() #?dict_items135 if not k.startswith('_')} #?skip_private136137138# Base classes representing different domains #?domain_bases139140class Entity: #?entity_class141 """Base for database entities."""142143 def __init__(self): #?entity_init144 self._id = None #?entity_id145146 def get_name(self) -> str: #?get_name_entity147 raise NotImplementedError #?not_implemented148149150class Item: #?item_class151 """Base for store items."""152153 def __init__(self): #?item_init154 self._sku = None #?item_sku155156 def get_name(self) -> str: #?get_name_item157 raise NotImplementedError #?not_implemented_item158159160# Classes using mixin with their own base classes #?using_mixin_with_base161162class User(Entity, SerializableMixin): #?user_class163 """User IS-A Entity, HAS serialization."""164165 def __init__(self, username: str, email: str): #?user_init166 super().__init__() #?user_super167 self.username→ alice = usernamealice #?set_username168 self.email→ alice@example.com = emailalice@example.com #?set_emaildef __init__(self, name: str, price: float): #?product_init
177def __init__(self⟨Product D⟩, nameLaptop: str, price999.99: float): #?product_init178 super().__init__() #?product_super179 self.name = name #?set_nameself._sku ← None
153def __init__(self⟨Product D⟩): #?item_init154 self._sku→ None = None #?item_skuself.name ← Laptop, self.price ← 999.99, product ← ⟨Product D⟩
46 user = User("alice", "alice@example.com") #?create_user47 product→ ⟨Product D⟩ = Product("Laptop", 999.99) #?create_product4849 print(f"User: {user⟨User C⟩.get_name()}") #?user_name50 print(f"User serialized: {user.to_dict()}") #?user_serialized5152 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self, message: str): #?log_method117 print(f"[{self.__class__.__name__}] {message}") #?print_log118119120class LoggedDog(Animal, LoggingMixin): #?logged_dog121 """Dog with logging capability added."""122123 def speak(self): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?bark126127128# Comparison: Adding serialization #?serialization_comparison129130class SerializableMixin: #?serializable_mixin131 """Mixin - adds serialization CAPABILITY."""132133 def to_dict(self) -> dict: #?to_dict134 return {k: v for k, v in self.__dict__.items() #?dict_items135 if not k.startswith('_')} #?skip_private136137138# Base classes representing different domains #?domain_bases139140class Entity: #?entity_class141 """Base for database entities."""142143 def __init__(self): #?entity_init144 self._id = None #?entity_id145146 def get_name(self) -> str: #?get_name_entity147 raise NotImplementedError #?not_implemented148149150class Item: #?item_class151 """Base for store items."""152153 def __init__(self): #?item_init154 self._sku = None #?item_sku155156 def get_name(self) -> str: #?get_name_item157 raise NotImplementedError #?not_implemented_item158159160# Classes using mixin with their own base classes #?using_mixin_with_base161162class User(Entity, SerializableMixin): #?user_class163 """User IS-A Entity, HAS serialization."""164165 def __init__(self, username: str, email: str): #?user_init166 super().__init__() #?user_super167 self.username = username #?set_username168 self.email = email #?set_email169170 def get_name(self) -> str: #?user_get_name171 return self.username #?return_username172173174class Product(Item, SerializableMixin): #?product_class175 """Product IS-A Item, HAS serialization."""176177 def __init__(self, name: str, price: float): #?product_init178 super().__init__() #?product_super179 self.name→ Laptop = nameLaptop #?set_name180 self.price→ 999.99 = price999.99 #?set_pricedef get_name(self) -> str: #?user_get_name
170def get_name(self⟨User C⟩) -> str: #?user_get_name171 return self.usernamealice #?return_usernameprint(f"User: {user.get_name()}") #?user_name
49print(f"User: {user⟨User C⟩.get_name()}") #?user_name50print(f"User serialized: {user⟨User C⟩.to_dict()}") #?user_serializedoutputUser: alicedef to_dict(self) -> dict: #?to_dict
pass 1 of 2133def to_dict(self⟨User C⟩) -> dict: #?to_dict134 return {k(empty): v(empty) for k, v in self.__dict__{'_id': None, 'username': 'alice', 'email': 'alice@example.com'}.items() #?dict_items135 if not k(empty).startswith('_')} #?skip_privateprint(f"User serialized: {user.to_dict()}") #?user_serialized
49print(f"User: {user.get_name()}") #?user_name50print(f"User serialized: {user⟨User C⟩.to_dict()}") #?user_serialized5152print(f"Product: {product⟨Product D⟩.get_name()}") #?product_name53print(f"Product serialized: {product.to_dict()}") #?product_serializedoutputUser serialized: {'username': 'alice', 'email': 'alice@example.com'}def get_name(self) -> str: #?product_get_name
182def get_name(self⟨Product D⟩) -> str: #?product_get_name183 return self.nameLaptop #?return_nameprint(f"Product: {product.get_name()}") #?product_name
52print(f"Product: {product⟨Product D⟩.get_name()}") #?product_name53print(f"Product serialized: {product⟨Product D⟩.to_dict()}") #?product_serializedoutputProduct: Laptopdef to_dict(self) -> dict: #?to_dict
pass 2 of 2133def to_dict(self⟨Product D⟩) -> dict: #?to_dict134 return {k(empty): v(empty) for k, v in self.__dict__{'_sku': None, 'name': 'Laptop', 'price': 999.99}.items() #?dict_items135 if not k(empty).startswith('_')} #?skip_privateprint(f"Product serialized: {product.to_dict()}") #?product_serialized
52 print(f"Product: {product.get_name()}") #?product_name53 print(f"Product serialized: {product⟨Product D⟩.to_dict()}") #?product_serialized5455 # Decision guide #?decision_guide56 print("\n=== Decision Guide ===")57 print("""58 Use REGULAR INHERITANCE when:59 ┌─────────────────────────────────────────────────┐60 │ • Clear IS-A relationship (Dog IS-A Animal) │61 │ • Shared state and behavior │62 │ • Objects are naturally in same hierarchy │63 │ • Want to override parent methods │64 └─────────────────────────────────────────────────┘6566 Use MIXIN when:67 ┌─────────────────────────────────────────────────┐68 │ • Adding capability (HAS-A behavior) │69 │ • Unrelated classes need same feature │70 │ • Small, focused functionality │71 │ • No shared identity/state │72 │ • Want to compose behaviors flexibly │73 └─────────────────────────────────────────────────┘74 """)7576 # Anti-patterns #?anti_patterns77 print("=== Anti-Patterns to Avoid ===")78 print("""79 ✗ Mixin with complex state (use regular class)80 ✗ Mixin that depends on other mixins (order issues)81 ✗ Too many mixins (hard to understand)82 ✗ Using inheritance just for code reuse83 ✗ Deep inheritance hierarchies84 """)858687# Regular Inheritance Example #?regular_inheritance8889class Animal: #?animal_class90 """Base class - defines what an animal IS."""9192 def __init__(self, name: str): #?animal_init93 self.name = name #?animal_name9495 def speak(self): #?animal_speak96 """Override in subclass."""97 print("Some sound") #?some_sound9899 def move(self): #?animal_move100 """Common to all animals."""101 print(f"{self.name} is moving") #?print_moving102103104class Dog(Animal): #?dog_class105 """Dog IS-A Animal - clear inheritance."""106107 def speak(self): #?dog_speak_method108 print("Woof!") #?woof109110111# Mixin Example #?mixin_example112113class LoggingMixin: #?logging_mixin114 """Adds logging CAPABILITY."""115116 def log(self, message: str): #?log_method117 print(f"[{self.__class__.__name__}] {message}") #?print_log118119120class LoggedDog(Animal, LoggingMixin): #?logged_dog121 """Dog with logging capability added."""122123 def speak(self): #?logged_dog_speak124 self.log("About to bark") #?log_bark125 print("Woof!") #?bark126127128# Comparison: Adding serialization #?serialization_comparison129130class SerializableMixin: #?serializable_mixin131 """Mixin - adds serialization CAPABILITY."""132133 def to_dict(self) -> dict: #?to_dict134 return {k: v for k, v in self.__dict__.items() #?dict_items135 if not k.startswith('_')} #?skip_private136137138# Base classes representing different domains #?domain_bases139140class Entity: #?entity_class141 """Base for database entities."""142143 def __init__(self): #?entity_init144 self._id = None #?entity_id145146 def get_name(self) -> str: #?get_name_entity147 raise NotImplementedError #?not_implemented148149150class Item: #?item_class151 """Base for store items."""152153 def __init__(self): #?item_init154 self._sku = None #?item_sku155156 def get_name(self) -> str: #?get_name_item157 raise NotImplementedError #?not_implemented_item158159160# Classes using mixin with their own base classes #?using_mixin_with_base161162class User(Entity, SerializableMixin): #?user_class163 """User IS-A Entity, HAS serialization."""164165 def __init__(self, username: str, email: str): #?user_init166 super().__init__() #?user_super167 self.username = username #?set_username168 self.email = email #?set_email169170 def get_name(self) -> str: #?user_get_name171 return self.username #?return_username172173174class Product(Item, SerializableMixin): #?product_class175 """Product IS-A Item, HAS serialization."""176177 def __init__(self, name: str, price: float): #?product_init178 super().__init__() #?product_super179 self.name = name #?set_name180 self.price = price #?set_price181182 def get_name(self) -> str: #?product_get_name183 return self.name #?return_name184185186if __name__ == "__main__":187 main()outputProduct serialized: {'name': 'Laptop', 'price': 999.99} === Decision Guide === Use REGULAR INHERITANCE when: ┌─────────────────────────────────────────────────┐ │ • Clear IS-A relationship (Dog IS-A Animal) │ │ • Shared state and behavior │ │ • Objects are naturally in same hierarchy │ │ • Want to override parent methods │ └─────────────────────────────────────────────────┘ Use MIXIN when: ┌─────────────────────────────────────────────────┐ │ • Adding capability (HAS-A behavior) │ │ • Unrelated classes need same feature │ │ • Small, focused functionality │ │ • No shared identity/state │ │ • Want to compose behaviors flexibly │ └─────────────────────────────────────────────────┘ === Anti-Patterns to Avoid === ✗ Mixin with complex state (use regular class) ✗ Mixin that depends on other mixins (order issues) ✗ Too many mixins (hard to understand) ✗ Using inheritance just for code reuse ✗ Deep inheritance hierarchies
Inheritance: "is-a" relationship. Mixin: "has capability". Choose wisely.
Exercise: practical.py
Build a web framework-style mixin system