🐹 파이썬의 상속

λ―Όλ‹¬νŒ½μ΄μš°μœ Β·2024λ…„ 6μ›” 2일

🐹 파이썬 기초

λͺ©λ‘ 보기
17/19

πŸ’‘ 1. 상속

νŒŒμ΄μ¬μ—μ„œ 상속은 ν•œ 클래슀의 속성과 λ©”μ„œλ“œλ₯Ό λ‹€λ₯Έ ν΄λž˜μŠ€μ— μ „λ‹¬ν•˜λŠ” κΈ°λŠ₯을 μ˜λ―Έν•œλ‹€. 상속을 μ‚¬μš©ν•˜λ©΄ 기쑴의 μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•˜κ³  ν™•μž₯ν•  수 μžˆλ‹€. 기본적으둜 파이썬의 λͺ¨λ“  ν΄λž˜μŠ€λŠ” objectλΌλŠ” κΈ°λ³Έ ν΄λž˜μŠ€λ‘œλΆ€ν„° μƒμ†λ°›λŠ”λ‹€.

μƒμ†μ˜ κΈ°λ³Έ ν˜•μ‹μ€ λ‹€μŒκ³Ό κ°™λ‹€.

class Parent:
    pass

class Child(Parent):
    pass
class Animal:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def eat(self, food):
    print(f'{self.name}이(κ°€) {food}λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.')

  def sleep(self, hour):
    print(f'{self.name}이(κ°€) {hour}μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.')
animal = Animal('동물', 10)
animal.eat('먹이')
animal.sleep(8)
> 동물이(κ°€) 먹이λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
> 동물이(κ°€) 8μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.
class Dog(Animal):
  pass
# Animal 클래슀λ₯Ό μƒμ†λ°›μ•˜κΈ° λ•Œλ¬Έμ— Animal 클래슀의 μƒμ„±μž λ§€κ°œλ³€μˆ˜λ₯Ό 전달해야 함
Rucy = Dog('μˆ‘μ΄', 5)
Rucy.eat('μ‚¬λ£Œ')
Rucy.sleep(12)
> μˆ‘μ΄μ΄(κ°€) μ‚¬λ£Œλ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
> μˆ‘μ΄μ΄(κ°€) 12μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.

πŸ’‘ 2. 클래슀 상속 μ‹œ μƒμ„±μž 호좜 μˆœμ„œ

  1. μžμ‹ 클래슀(child class)의 μƒμ„±μžκ°€ ν˜ΈμΆœλ©λ‹ˆλ‹€.
  2. μžμ‹ 클래슀의 μƒμ„±μžμ—μ„œ λΆ€λͺ¨ 클래슀(parent class)의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ super() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. super() ν•¨μˆ˜λŠ” ν˜„μž¬ 클래슀의 λΆ€λͺ¨ 클래슀λ₯Ό μ°Έμ‘°ν•˜λ©°, λΆ€λͺ¨ 클래슀의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. λΆ€λͺ¨ 클래슀의 μƒμ„±μžκ°€ ν˜ΈμΆœλ©λ‹ˆλ‹€.
  4. λΆ€λͺ¨ 클래슀의 μƒμ„±μžκ°€ 싀행을 마치면 μžμ‹ 클래슀의 μƒμ„±μžλ‘œ λŒμ•„κ°€ μžμ‹ 클래슀의 μƒμ„±μž μ½”λ“œκ°€ μ‹€ν–‰λ©λ‹ˆλ‹€.
class Parent:
  def __init__(self):
    print('λΆ€λͺ¨ 클래슀 μƒμ„±μž 호좜')

class Child(Parent):
  def __init__(self):
    print('Child 클래슀 μƒμ„±μž 호좜')
    super().__init__() # 상속 λ°›μ•˜μœΌλ©΄ 무쑰건 super 호좜
    print('μžμ‹ 클래슀 μƒμ„±μž 호좜')
child = Child()
> Child 클래슀 μƒμ„±μž 호좜
> λΆ€λͺ¨ 클래슀 μƒμ„±μž 호좜
> μžμ‹ 클래슀 μƒμ„±μž 호좜

πŸ’‘ 3. object 클래슀

objectλŠ” 파이썬의 λͺ¨λ“  클래슀의 κΈ°λ³Έ ν΄λž˜μŠ€μ΄λ‹€. object ν΄λž˜μŠ€λŠ” νŒŒμ΄μ¬μ—μ„œ λͺ¨λ“  객체의 기본적인 λ™μž‘κ³Ό νŠΉμ„±μ„ μ •μ˜ν•œλ‹€.

class MyClass:
    pass

# μœ„μ˜ μ½”λ“œλŠ” λ‹€μŒκ³Ό λ™μΌν•©λ‹ˆλ‹€.
class MyClass(object):
    pass

πŸ’‘ 4. λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©

λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©(Method Overriding)은 객체 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ€‘μš”ν•œ κ°œλ… 쀑 ν•˜λ‚˜λ‘œ, μ„œλΈŒ 클래슀(μžμ‹ 클래슀)μ—μ„œ 슈퍼 클래슀(λΆ€λͺ¨ 클래슀)의 λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€. μ˜€λ²„λΌμ΄λ”©μ„ μ‚¬μš©ν•˜λ©΄, μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œ 상속받은 λ©”μ„œλ“œμ˜ λ™μž‘μ„ λ³€κ²½ν•˜κ±°λ‚˜ ν™•μž₯ν•  수 μžˆλ‹€.

class Animal:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def eat(self, food):
    print(f'{self.name}이(κ°€) {food}λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.')

  def sleep(self, hour):
    print(f'{self.name}이(κ°€) {hour}μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.')
class Dog(Animal):
  def run(self):
    print(f'{self.name} λ‹¬λ¦½λ‹ˆλ‹€')
SSongi = Dog('μˆ‘μ΄', 5)
SSongi.eat('μ‚¬λ£Œ')
SSongi.sleep(8)
SSongi.run()
> μˆ‘μ΄μ΄(κ°€) μ‚¬λ£Œλ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
> μˆ‘μ΄μ΄(κ°€) 8μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.
> μˆ‘μ΄ λ‹¬λ¦½λ‹ˆλ‹€
class Animal:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def eat(self, food):
    print(f'{self.name}이(κ°€) {food}λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.')

  def sleep(self, hour):
    print(f'{self.name}이(κ°€) {hour}μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.')
class Dog(Animal):
  def run(self):
    print(f'{self.name} λ‹¬λ¦½λ‹ˆλ‹€')

  def eat(self, food):
    print(f'{self.name} {food}λ₯Ό μ•„μ£Ό λ§›μžˆκ²Œ λ¨ΉμŠ΅λ‹ˆλ‹€')

  def superEat(self, food):
    super().eat(food)
SSongi = Dog('μˆ‘μ΄', 5)
SSongi.eat('μ‚¬λ£Œ')
SSongi.superEat('μ‚¬λ£Œ')
> μˆ‘μ΄ μ‚¬λ£Œλ₯Ό μ•„μ£Ό λ§›μžˆκ²Œ λ¨ΉμŠ΅λ‹ˆλ‹€
> μˆ‘μ΄μ΄(κ°€) μ‚¬λ£Œλ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
animal = Animal('동물', 10)
animal.eat('먹이')
> 동물이(κ°€) 먹이λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
animal.run()
> AttributeError: 'Animal' object has no attribute 'run'

πŸ’‘ 5. 닀쀑 상속

닀쀑 상속은 ν΄λž˜μŠ€κ°€ λ‘˜ μ΄μƒμ˜ λΆ€λͺ¨ ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속을 λ°›λŠ” κΈ°λŠ₯을 μ˜λ―Έν•œλ‹€. νŒŒμ΄μ¬μ€ λ‹€λ₯Έ λ§Žμ€ 객체 μ§€ν–₯ 언어와 달리 닀쀑 상속을 μ§€μ›ν•œλ‹€. 닀쀑 μƒμ†ŒκΈ€ μ‚¬μš©ν•˜λ©΄ μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ„ ν–₯μƒμ‹œν‚¬ 수 μžˆμ§€λ§Œ, λ™μ‹œμ— λ³΅μž‘μ„±μ΄ λ†’μ•„μ§€κΈ° λ•Œλ¬Έμ— μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

닀쀑 μƒμ†μ˜ κΈ°λ³Έ ν˜•μ‹μ€ λ‹€μŒκ³Ό κ°™λ‹€.

class Parent1:
    pass

class Parent2:
    pass

class Child(Parent1, Parent2):
    pass
class Animal:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def eat(self, food):
    print(f'{self.name} {food}λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.')

  def sleep(self, hour):
    print(f'{self.name} {hour}μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.')
class Human:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def study(self, hour):
    print(f'{self.name} {hour}μ‹œκ°„ λ™μ•ˆ 곡뢀λ₯Ό ν•©λ‹ˆλ‹€.')

  def sleep(self, hour):
    print(f'{self.name} {hour}μ‹œκ°„ λ™μ•ˆ κΏ€μž μ„ μž‘λ‹ˆλ‹€.')
class YoominKong(Animal, Human):
  pass
Kong = YoominKong('유민콩', 5)
Kong.eat('λ§ˆλΌνƒ•')
Kong.study(2)
Kong.sleep(8) # Animal의 sleepλ₯Ό μƒμ†λ°›μŒ.
> 유민콩 λ§ˆλΌνƒ•λ₯Ό λ¨ΉμŠ΅λ‹ˆλ‹€.
> 유민콩 2μ‹œκ°„ λ™μ•ˆ 곡뢀λ₯Ό ν•©λ‹ˆλ‹€.
> 유민콩 8μ‹œκ°„ λ™μ•ˆ μž μ„ μž‘λ‹ˆλ‹€.
print(YoominKong.mro()) # λ©”μ†Œλ“œκ°€ 겹쳀을 λ•Œ μ–΄λŠ μˆœμ„œλ‘œ λΆˆλ¦¬λŠ” μ§€ μ•Œλ €μ€Œ
> [<class '__main__.YoominKong'>, <class '__main__.Animal'>, <class '__main__.Human'>, <class 'object'>]

C3 μ„ ν˜•ν™” μ•Œκ³ λ¦¬μ¦˜

  • Python의 닀쀑 μƒμ†μ—μ„œ λ©”μ„œλ“œ ν•΄κ²° μˆœμ„œ(Method Resolution Order, MRO)λ₯Ό κ³„μ‚°ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” μ•Œκ³ λ¦¬μ¦˜
  • λ³΅μž‘ν•œ 상속 κ΅¬μ‘°μ—μ„œ λ©”μ„œλ“œ 호좜 μˆœμ„œλ₯Ό λͺ…ν™•ν•˜κ²Œ κ²°μ •ν•˜κΈ° μœ„ν•΄ κ³ μ•ˆλœ μ•Œκ³ λ¦¬μ¦˜

πŸ’‘ 6. super() λ©”μ„œλ“œ

super()λŠ” 파이썬의 λ‚΄μž₯ ν•¨μˆ˜λ‘œμ„œ, 상속과 κ΄€λ ¨λœ μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μ‚¬μš©λœλ‹€. 특히, μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ μ‚¬μš©λœλ‹€. super()의 μ£Όμš” λͺ©μ μ€ μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ(μž¬μ •μ˜)ν•˜λ©΄μ„œλ„ κ·Έ μ˜€λ²„λΌμ΄λ“œλœ λ©”μ„œλ“œ λ‚΄μ—μ„œ λΆ€λͺ¨ 클래슀의 원본 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 것이닀.

6-1. 기본적인 μ‚¬μš©

class Parent:
  def hello(self):
    print('λΆ€λͺ¨ 클래슀의 hello λ©”μ„œλ“œ')

class Child(Parent):
  def hello(self):
    super().hello()
    print('μžμ‹ 클래슀의 hello λ©”μ„œλ“œ')
child = Child()
child.hello()
> λΆ€λͺ¨ 클래슀의 hello λ©”μ„œλ“œ
> μžμ‹ 클래슀의 hello λ©”μ„œλ“œ

6-2. init() λ©”μ„œλ“œμ˜ μ‚¬μš©

class Parent:
  def __init__(self, value):
    self.value = value

class Child(Parent):
  def __init__(self, value, child_value):
    super().__init__(value)
    self.child_value = child_value
child = Child(10, 20)
print(child.child_value) # 10은 super(Parent)둜 λ“€μ–΄κ°€μ„œ child_valueλŠ” 20이 됨
print(child.value)
> 20
> 10
parent = Parent(10)
print(parent.value)
> 10

6-3. 닀쀑 μƒμ†μ—μ„œμ˜ μ‚¬μš©

class Base:
  def hello(self):
    print('Base의 hello()')
    print('Base 클래슀의 hello() λ©”μ„œλ“œ')

class A(Base):
  def hello(self):
    print('A의 hello()')
    super().hello()
    print('A 클래슀의 hello() λ©”μ„œλ“œ')

class B(Base):
  def hello(self):
    print('B의 hello()')
    super().hello()
    print('B 클래슀의 hello() λ©”μ„œλ“œ')

class Child(A, B):
  def hello(self):
    print('Child의 hello()')
    super().hello()
    print('Child 클래슀의 hello() λ©”μ„œλ“œ')
child = Child()
child.hello() # child 좜λ ₯되고 super λ•Œλ¬Έμ— A둜 κ°€μ„œ A의 ν”„λ¦°νŠΈ 찍히고 밑에 super λ•Œλ¬Έμ— B둜 κ°€κ³  또 Bμ—μ„œ Base κΉŒμ§€ κ°„ λ‹€μŒμ— λ°˜λŒ€μˆœμ„œλŒ€λ‘œ λ§ˆμ§€λ§‰μ€„ print문이 μ°¨λ‘€μ°¨λ‘€ 좜λ ₯됨
> Child의 hello()
> A의 hello()
> B의 hello()
> Base의 hello()
> Base 클래슀의 hello() λ©”μ„œλ“œ
> B 클래슀의 hello() λ©”μ„œλ“œ
> A 클래슀의 hello() λ©”μ„œλ“œ
> Child 클래슀의 hello() λ©”μ„œλ“œ
Child.mro() # μœ„μ˜ 좜λ ₯ 결과와 λ™μΌν•œ μˆœμ„œ. 즉 닀쀑 μƒμ†μ‹œ mro에 μ˜ν•œ μˆœμ„œλŒ€λ‘œ 진행됨. 이 μˆœμ„œλŠ” μ•Œκ³ λ¦¬μ¦˜μ— μ˜ν•΄ μ •ν•΄μ§€κΈ° λ•Œλ¬Έμ— λ‹€μ€‘μƒμ†μ΄λ‚˜ λ©”μ„œλ“œ 이름이 κ²ΉμΉ˜λŠ” 경우 mroλ₯Ό ν™•μΈν•΄λ³΄λŠ” 게 μ’‹λ‹€.
> [__main__.Child, __main__.A, __main__.B, __main__.Base, object]
profile
μ–΄λ–»κ²Œ ν–„μŠ€ν„°κ°€ 개발자

0개의 λŒ“κΈ€