본문 바로가기
코딩/파이썬

파이썬 상속

by Song1234 2024. 3. 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(10)

결과:
동물은(는) 먹이를 먹습니다.
동물은(는) 10시간 동안 잠을 잡니다.

class Dog(Animal): #Animal 클래스 상속
    pass
# Animal 클래스를 상속 받았기 때문에 Animal 클래스의 생성자 매개변수를 전달해야 함
# Rucy = Dog('')
Rucy = Dog('루시', 14)
Rucy.eat('사료')
Rucy.sleep(10)

결과:
루시은(는) 사료를 먹습니다.
루시은(는) 10시간 동안 잠을 잡니다.


2. 클래스 상속 시 생성자 호출 순서

  1. 자식 클래스(Child Class)의 생성자가 호출
  2. 자식 클래스의 생성자에서 부모 클래스의 생성자가 호출
  3. 만약 자식 생성자에서 부모 생성자로 직접 호출할 경우 super() 함수를 사용
  4. 부모 클래스의 생성자가 실행을 마치면 자식 클래스의 생성자로 돌아가 자식 클래스의 생성자 코드가 실행
class Parent:
    def __init__(self): # (3) 부모 생성자 호출
        print('부모 클래스 생성자 호출')

class Child(Parent):
    def __init__(self): # (1) 자식 클래스 생성자 호출
        print('Child 클래스 생성자 호출')
        super().__init__() # (2) 부모 생성자 직접호출
        print('자식 클래스 생성자 호출') #(4) # 자식 클래스 생성자 코드 실행
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}은(는) 달립니다.')
Rucy = Dog('루시', 14)
Rucy.eat('사료')
Rucy.run()

루시은(는) 사료를 먹습니다.
루시은(는) 달립니다.

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)
Rucy = Dog('루시', 14)
Rucy.eat('사료')
Rucy.run()

루시은(는) 사료를 아주 맛있게 먹습니다.
루시은(는) 달립니다.

Rucy.superEat('사료') #super()를 사용해 부모 클래스의 메서드를 사용

루시은(는) 사료를 먹습니다.

animal = Animal('동물', 10)
animal.eat('먹이')
# animal.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 KimApple(Animal, Human): # 두개의 부모클래스 상속
    pass
kim = KimApple('김사과', 20) # 객체 생성과 매개변수 값 입력
kim.eat('밥')
kim.study(2)
kim.sleep(8)

김사과은(는) 밥를 먹습니다.
김사과은(는) 2시간 동안 공부를 합니다.
김사과은(는) 8시간 동안 잠을 잡니다.

C3 선형화 알고리즘

다중상속을 했을때 부모클래스가 동일한 부모 클래스를 가졌을때 다이아몬드 문제가 발생한다.

  • Python의 다중 상속에서 메서드 해결 순서를(Method Resolution Order, MRO)를 계산하는데 사용되는 알고리즘

  • 복잡한 상속 구조에서 메서드 호출 순서를 명확하게 결정하기 위해 고안된 알고리즘

    print(KimApple.mro())

    결과:
    [<class 'main.KimApple'>, <class 'main.Animal'>, <class 'main.Human'>, <class 'object'>]


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)
print(child.value)

20
10

자식 생성자가 있으면 부모의 생성자가 호출되지 않기때문에 직접 부모의 생성자를 호출해야함.

6-3. 다중 상속에서의 사용

# 다이아몬드 구조생성
class Base:
    def hello(self):
        print('Base 클래스의 hello 메서드')

class A(Base):
    def hello(self):
        super().hello()
        print('A 클래스의 hello 메서드')

class B(Base):
    def hello(self):
        super().hello()
        print('B 클래스의 hello 메서드')

class Child(A, B):
    def hello(self):
        super().hello()
        print('Child 클래스의 hello 메서드 호출')
Child.mro()

[main.Child, main.A, main.B, main.Base, object]

child = Child()
child.hello()

Base 클래스의 hello 메서드
B 클래스의 hello 메서드
A 클래스의 hello 메서드
Child 클래스의 hello 메서드 호출

A,B는 Base에게 Child 는 A,B에게 상속받았다.
Child 를 실행시키면 Child -> A -> B -> Base 순으로 올라가고,
다시 내려올때 반대순서로 내려온다 Base에서 자식인 B로 B에서 A로 A에서 Child 으로 내려오게된다.
(Base -> B -> A -> Child)

'코딩 > 파이썬' 카테고리의 다른 글

파이썬 예외처리  (1) 2024.03.20
스페셜 메서드  (0) 2024.03.19
클로저와 데코레이터  (1) 2024.03.19
파이썬 - 객체지향과 클래스  (3) 2024.03.18
파이썬 - 콜백함수와 람다함수  (1) 2024.03.18