KR_Inheritance - somaz94/python-study GitHub Wiki
ν΄λμ€ κ°μ μ½λ μ¬μ¬μ©μ μν λ©μ»€λμ¦μ΄λ€.
# κΈ°λ³Έ μμ
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return f"{self.name}κ° λ©λ©!"
class Cat(Animal):
def speak(self):
return f"{self.name}κ° μΌμΉ!"
dog = Dog("λ©λ©μ΄")
print(dog.speak()) # λ©λ©μ΄κ° λ©λ©!
# μμ κ΄κ³ νμΈ
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True
print(issubclass(Dog, Animal)) # True
# λ©μλ μΆκ°
class Bird(Animal):
def speak(self):
return f"{self.name}κ° μ§Ήμ§Ή!"
def fly(self):
return f"{self.name}κ° λ μκ°λλ€!"
β
νΉμ§:
- μ½λ μ¬μ¬μ©
- λ©μλ μ€λ²λΌμ΄λ©
- κ³μΈ΅ ꡬ쑰
- is-a κ΄κ³ νν
- κ³΅ν΅ μΈν°νμ΄μ€ μ 곡
Pythonμ μ¬λ¬ ν΄λμ€λ₯Ό λμμ μμλ°μ μ μλ λ€μ€ μμμ μ§μνλ€.
class Flying:
def fly(self):
return "λ μ μμ"
class Swimming:
def swim(self):
return "μμν μ μμ"
class Duck(Flying, Swimming):
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name}μ΄ κ½₯κ½₯!"
# λ€μ€ μμ μ¬μ©
duck = Duck("λλλ")
print(duck.fly()) # λ μ μμ
print(duck.swim()) # μμν μ μμ
print(duck.speak()) # λλλμ΄ κ½₯κ½₯!
# λ©μλ ν΄μ μμ(MRO) νμΈ
print(Duck.__mro__)
# λ€μ΄μλͺ¬λ λ¬Έμ
class A:
def who_am_i(self):
return "I am A"
class B(A):
def who_am_i(self):
return "I am B"
class C(A):
def who_am_i(self):
return "I am C"
class D(B, C):
pass
# Dμ who_am_iλ Bμ λ©μλκ° νΈμΆλ¨
print(D().who_am_i()) # I am B
print(D.__mro__) # λ©μλ ν΄μ μμ νμΈ
β
νΉμ§:
- μ¬λ¬ ν΄λμ€ μμ
- κΈ°λ₯ μ‘°ν©
- Method Resolution Order (MRO) κ³ λ €
- λ€μ΄μλͺ¬λ λ¬Έμ ν΄κ²°
- C3 μ νν μκ³ λ¦¬μ¦ μ¬μ©
λΆλͺ¨ ν΄λμ€μ λ©μλλ₯Ό νΈμΆνκΈ° μν λ΄μ₯ ν¨μμ΄λ€.
class Parent:
def __init__(self, name):
self.name = name
def greet(self):
return f"μλ
, λλ {self.name}"
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # λΆλͺ¨ ν΄λμ€μ __init__ νΈμΆ
self.age = age
def greet(self):
return super().greet() + f", {self.age}μ΄μ΄μΌ"
# super() μ¬μ©
child = Child("μν¬", 10)
print(child.greet()) # μλ
, λλ μν¬, 10μ΄μ΄μΌ
# λ€μ€ μμμμμ super()
class A:
def method(self):
print("A.method νΈμΆ")
class B(A):
def method(self):
print("B.method νΈμΆ")
super().method()
class C(A):
def method(self):
print("C.method νΈμΆ")
super().method()
class D(B, C):
def method(self):
print("D.method νΈμΆ")
super().method()
# MROλ₯Ό λ°λΌ D -> B -> C -> A μμλ‘ λ©μλ νΈμΆ
D().method()
β
νΉμ§:
- λΆλͺ¨ ν΄λμ€ λ©μλ νΈμΆ
- μ΄κΈ°ν 체μΈ
- λ©μλ νμ₯
- λ€μ€ μμμμμ MRO νμ©
- μ½λ μ€λ³΅ λ°©μ§
- μ μ§λ³΄μμ± ν₯μ
μΆμ ν΄λμ€λ νμ ν΄λμ€κ° ꡬνν΄μΌ νλ λ©μλλ₯Ό μ μνλ νμ΄λ€.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2
def perimeter(self):
import math
return 2 * math.pi * self.radius
# μΆμ ν΄λμ€λ μΈμ€ν΄μ€νν μ μμ
# shape = Shape() # TypeError λ°μ
# λͺ¨λ μΆμ λ©μλλ₯Ό ꡬννμ§ μμΌλ©΄ μλ¬ λ°μ
# class InvalidShape(Shape):
# def area(self):
# return 0
# # perimeter λ©μλκ° μμ΄ μλ¬ λ°μ
# λ€νμ± νμ©
shapes = [Rectangle(5, 4), Circle(3)]
for shape in shapes:
print(f"λ©΄μ : {shape.area():.2f}, λλ : {shape.perimeter():.2f}")
β
νΉμ§:
- μΈν°νμ΄μ€ μ μ
- ꡬν κ°μ
- μ€κ³ λͺ νν
- λ€νμ± μ§μ
- λ©μλ μκ·Έλμ² νμ€ν
- μ½λ νμ§ κ°μ
λ―Ήμ€μΈμ μμμ ν΅ν΄ ν΄λμ€μ κΈ°λ₯μ μΆκ°νλ λ°©λ²μ΄λ€.
class JSONMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class CSVMixin:
def to_csv(self):
return ",".join(str(v) for v in self.__dict__.values())
class User(JSONMixin, CSVMixin):
def __init__(self, name, age):
self.name = name
self.age = age
user = User("νκΈΈλ", 30)
print(user.to_json()) # {"name": "νκΈΈλ", "age": 30}
print(user.to_csv()) # νκΈΈλ,30
# λ€μν λ―Ήμ€μΈ μ‘°ν©
class LoggingMixin:
def log(self, message):
print(f"[LOG] {message}")
class ValidationMixin:
def validate(self):
for key, value in self.__dict__.items():
if value is None:
return False
return True
class Product(JSONMixin, LoggingMixin, ValidationMixin):
def __init__(self, name, price, description=None):
self.name = name
self.price = price
self.description = description
self.log(f"Product created: {name}")
product = Product("λ
ΈνΈλΆ", 1500000)
print(product.validate()) # True
print(product.to_json()) # {"name": "λ
ΈνΈλΆ", "price": 1500000, "description": null}
β
νΉμ§:
- κΈ°λ₯ μ¬μ¬μ©
- μ½λ λͺ¨λν
- μ μ°ν νμ₯
- κ΄μ¬μ¬ λΆλ¦¬
- λ€μ€ μμ ν¨ν΄
- λ¨μΌ μ± μ μμΉ μ€μ
- κ΅¬μ± κ°λ₯ν λμ
μμλ°μ λ©μλλ₯Ό μ¬μ μνμ¬ λ€μν ννλ‘ λμνκ² νλ κ°λ
μ΄λ€.
# λ©μλ μ€λ²λΌμ΄λ©
class Vehicle:
def __init__(self, name):
self.name = name
def start(self):
return f"{self.name} μλμ κ²λλ€."
def move(self):
return f"{self.name} μ΄λ μ€"
class Car(Vehicle):
def start(self):
return f"{self.name} μμ§μ μΌλλ€."
def move(self):
return f"{self.name} λλ‘λ₯Ό λ¬λ¦½λλ€."
class Boat(Vehicle):
def start(self):
return f"{self.name} λͺ¨ν°λ₯Ό κ°λν©λλ€."
def move(self):
return f"{self.name} λ¬Ό μλ₯Ό νν΄ν©λλ€."
# λ€νμ± νμ©
vehicles = [Vehicle("μ΄μ‘μλ¨"), Car("μλν"), Boat("μνΈ")]
for vehicle in vehicles:
print(vehicle.start())
print(vehicle.move())
# λΆλΆ λ©μλ μ€λ²λΌμ΄λ©
class ElectricCar(Car):
def start(self):
# λΆλͺ¨ λ©μλλ₯Ό νΈμΆν ν νμ₯
parent_result = super().start()
return f"{parent_result} (μ κΈ°λͺ¨ν° νμ±ν)"
# move λ©μλλ μ€λ²λΌμ΄λ©νμ§ μμ (Carμ λ©μλ μ¬μ©)
electric_car = ElectricCar("ν
μ¬λΌ")
print(electric_car.start()) # ν
μ¬λΌ μμ§μ μΌλλ€. (μ κΈ°λͺ¨ν° νμ±ν)
print(electric_car.move()) # ν
μ¬λΌ λλ‘λ₯Ό λ¬λ¦½λλ€.
β
νΉμ§:
- μμ ν΄λμ€μμ λ©μλ μ¬μ μ
- λ€μν ꡬν μ 곡
- λμΌν μΈν°νμ΄μ€
- λ°νμ λ€νμ±
- μ½λ μ μ°μ±
- νμ₯μ± ν₯μ
- λΆλΆμ μ€λ²λΌμ΄λ© κ°λ₯
μμκ³Ό ꡬμ±(Composition)μ μ½λ μ¬μ¬μ©μ μν λ κ°μ§ μ£Όμ λ°©λ²μ΄λ€.
# μμ λ°©μ (is-a κ΄κ³)
class Engine:
def start(self):
return "μμ§ μλ"
def stop(self):
return "μμ§ μ μ§"
class Car(Engine): # Car is an Engine (?)
def drive(self):
return f"{self.start()} ν μ£Όν"
# κ΅¬μ± λ°©μ (has-a κ΄κ³)
class BetterCar:
def __init__(self):
self.engine = Engine() # Car has an Engine
def drive(self):
return f"{self.engine.start()} ν μ£Όν"
def park(self):
return f"μ£Όμ°¨ ν {self.engine.stop()}"
# λ 볡μ‘ν, μ μ°ν κ΅¬μ± μμ
class SteeringWheel:
def turn_left(self):
return "μ’νμ "
def turn_right(self):
return "μ°νμ "
class Wheel:
def rotate(self):
return "λ°ν΄ νμ "
class AdvancedCar:
def __init__(self, engine_type):
if engine_type == "gasoline":
self.engine = Engine()
elif engine_type == "electric":
self.engine = ElectricEngine()
self.steering = SteeringWheel()
self.wheels = [Wheel() for _ in range(4)]
def drive(self):
return f"{self.engine.start()}, {self.wheels[0].rotate()}"
def turn(self, direction):
if direction == "left":
return self.steering.turn_left()
else:
return self.steering.turn_right()
β
νΉμ§:
- μμ: is-a κ΄κ³ νν
- ꡬμ±: has-a κ΄κ³ νν
- ꡬμ±μ λ μ μ°ν μ€κ³ μ 곡
- ꡬμ±μ λ°νμμ ꡬμ±μμ λ³κ²½ κ°λ₯
- "μμλ³΄λ€ κ΅¬μ±μ μ νΈνλΌ" μμΉ
- κΈ°λ₯ μ¬μ¬μ©μ μν λμμ μ κ·Όλ²
- μμ‘΄μ± κ΄λ¦¬ μ©μ΄
λ€μ€ μμμ 볡μ‘μ±μ κ΄λ¦¬νκ³ ν¨κ³Όμ μΌλ‘ νμ©νλ κ³ κΈ κΈ°λ²μ΄λ€.
# νλ ₯μ λ€μ€ μμ (Cooperative Multiple Inheritance)
class Base:
def __init__(self):
print("Base.__init__")
class A(Base):
def __init__(self):
super().__init__()
print("A.__init__")
class B(Base):
def __init__(self):
super().__init__()
print("B.__init__")
class C(A, B):
def __init__(self):
super().__init__()
print("C.__init__")
# μΆλ ₯:
# Base.__init__ (ν λ²λ§ νΈμΆλ¨)
# B.__init__
# A.__init__
# C.__init__
c = C()
print(C.__mro__)
# λ―Ήμ€μΈκ³Ό κΈ°λ³Έ ν΄λμ€μ μ‘°ν©
class Serializable:
def serialize(self):
return str(self.__dict__)
class Loggable:
def log(self, message):
print(f"[LOG] {message}")
class Displayable:
def display(self):
print(str(self))
class GameObject(Serializable, Loggable, Displayable):
def __init__(self, x, y, name):
self.x = x
self.y = y
self.name = name
self.log(f"Created {name} at ({x}, {y})")
def __str__(self):
return f"{self.name} at ({self.x}, {self.y})"
# λ€μ€ μμκ³Ό λͺ
λͺ
λ νν
from collections import namedtuple
from dataclasses import dataclass
Point = namedtuple('Point', ['x', 'y'])
@dataclass
class ColorPoint(Point): # λͺ
λͺ
λ νν μμ
color: str = "black"
def __init__(self, x, y, color="black"):
super().__init__(x, y) # μ€ν¨! namedtuple νμ₯ μ μ£Όμ
β
νΉμ§:
- νλ ₯μ λ€μ€ μμ
- MRO κΉμ΄ μ΄ν΄
- λ―Ήμ€μΈ κ³μΈ΅ ꡬ쑰
- λ€μ€ μμ λμμΈ ν¨ν΄
- μμ μ ν λ° μ£Όμμ
- namedtuple, dataclass μμ μ£Όμ
- μΈν°νμ΄μ€ μ‘°ν©
β
λͺ¨λ² μ¬λ‘:
- λ¨μΌ μμ μ°μ μ¬μ©
- λ€μ€ μμ μ MRO κ³ λ €
- μΆμ ν΄λμ€λ‘ μΈν°νμ΄μ€ μ μ
- super() νμ©νμ¬ λΆλͺ¨ ν΄λμ€ λ©μλ νΈμΆ
- μ μ ν λ©μλ μ€λ²λΌμ΄λ©μΌλ‘ λ€νμ± κ΅¬ν
- λ―Ήμ€μΈμΌλ‘ κΈ°λ₯ νμ₯
- νμ κ²μ¬ νμ© (isinstance, issubclass)
- λͺ νν κ³μΈ΅ ꡬ쑰 μ€κ³
- "μμλ³΄λ€ κ΅¬μ±μ μ νΈνλΌ" μμΉ κ³ λ €
- κΉμ μμ κ³μΈ΅ νΌνκΈ° (3-4λ¨κ³ μ΄ν μ μ§)
- κ³΅ν΅ κΈ°λ₯μ μμ ν΄λμ€λ‘ μ΄λ
- νλ ₯μ λ©μλ νΈμΆ ν¨ν΄ μ¬μ©
- μΆμν μμ€ μΌκ΄μ± μ μ§
- 리μ€μ½ν μΉν μμΉ μ€μ
- λͺ νν is-a κ΄κ³λ§ μμ μ¬μ©
- has-a κ΄κ³λ κ΅¬μ± μ¬μ©