본문 바로가기
파이썬/파이썬 기초 문법

파이썬 상속

by 쵠몽 2024. 10. 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)

 

class Cat(Animal):
    pass
# Animal 클래스를 상속 받았기 때문에 Animal 클래스의 생성자 매개변수 전달
Manbo = Cat('만보', 13)
Manbo.eat('사료')
Manbo.sleep(12)

 

 

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

  1. 자식 클래스(child class)의 생성자 호출가 호출된다.
  2. 자식 클래스의 생성자에서 부모 클래스(parent class)의 생성자를 호출해야 하는데, 이를 위해 super() 함수를 사용한다. super() 함수는 현재 클래스의 부모 클래스를 참조하며 부모 클래스의 생성자를 호출할 수 있다.
  3. 부모 클래스의 생성자가 호출된다.
  4. 부모 클래스의 생성자가 실행을 마치면서 자식 클래스의 생성자로 돌아가 자식 클래스의 생성자 코드가 실행된다.
class Parent:
    def __init__(self):
        print('부모 클래스 생성자 호출')      # 2

class Child(Parent):
    def __init__(self):
        print('Child 클래스 생성자 호출')     # 출력 순서: 1
        super().__init__()
        print('모든 생성자 호출 완료')        # 3

child = Child()

 

 

3. object 클래스

  • 파이썬에서 모든 클래스의 부모 클래스 역할을 하는 기본 클래스
  • 파이썬에서 정의하는 모든 클래스는 자동으로 object 클래스를 상속받아, 이 클래스에서 제공하는 기본적인 동작과 메서드를 사용할 수 있게 됨
  • 예) __srt__(), __repr__(), __eq__(), __hash__() 등
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 Cat(Animal):
    def run(self):
        print(f'{self.name} 달립니다')
Manbo = Cat('만보', 13)
Manbo.eat('사료')
Manbo.sleep('12')
Manbo.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 Cat(Animal):
    def run(self):
        print(f'{self.name} 달립니다')

    # 시그니처: 메서드의 이름, 매개변수의 타입과 개수 모두 일치해야 함
    def eat(self, food):
        print(f'{self.name} {food}를 아주 맛있게 먹습니다')

    def superEat(self, food):
        super().eat(food)
Manbo = Cat('만보', 13)
Manbo.eat('사료')
Manbo.sleep('12')
Manbo.run()

Manbo.superEat('사료')

animal = Animal('동물', 10)
animal.eat('먹이')
animal.sleep(10)
# animal.run() # AttributeError: 'Animal' object has no attribute 'run'
# 부모는 자식 클래스에만 존재하는 것은 사용 불가능

 

 

5. 다중 상속

  • 둘 이상의 부모 클래스로부터 상속을 받는 기능
  • 다중 상속은 코드의 재사용성을 향상시키지만 동시에 복잡성이 높아지므로 사용 시 주의해야 함
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 Kim(Animal, Human):
    pass
class Kim(Animal, Human):
    pass
    
kim = Kim('김사과', 20)
kim.eat('밥')
kim.study(2)
kim.sleep(8) # Animal 클래스의 sleep이 동작
print(Kim.mro())
# [<class '__main__.Kim'>, <class '__main__.Animal'>, <class '__main__.Human'>, <class 'object'>]
# Animal 클래스가 우선 순위

 

 

C3  선형화 알고리즘

  • 파이썬의 다중 상속에서 메서드 해결 순서(Method Resolution Order, MRO)를 계산하는 데 사용되는 알고리즘
  • 복잡한 상속 구조에서 메서드 호출 순서를 명확하게 결정하기 위해 고안됨
  • C3 선형화 규칙
    • 자식 클래스가 항상 부모 클래스보다 먼저 온다.
    • 부모 클래스들은 상속된 순서대로 나타난다.
    • 충돌을 해결할 때는 왼쪽에 있는 부모 클래스의 순서를 우선시한다.
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, height):
        self.name = name
        self.age = age
        self.height = height

    def study(self, hour):
        print(f'{self.name} {hour}시간 동안 공부를 합니다')

    def sleep(self, hour):
        print(f'키가 {self.height}인 {self.name} {hour}시간 동안 꿀잠 잡니다')

class Kim(Animal, Human):
    def __init__(self, name, age, height):
        Animal.__init__(self, name, age)
        Human.__init__(self, name, age, height)

    def sleep(self, hour):
        Human.sleep(self, hour)		# Human 부모 클래스 상속
kim = Kim('김사과', 20, 160)
kim.eat('밥')
kim.study(2)
kim.sleep(8)	# 자식 클래스에 있는 sleep() 동작

 

 

6. super() 함수

  • 파이썬의 내장 함수로서 상속과 관련된 작업 수행 시 사용됨
  • 자식 클래스에서 부모 클래스의 메서드를 호출할 때 주로 사용
  • 자식 클래스에서 부모 클래스의 메서드를 오버라이드(재정의)하면서도 오버라이드된 메서드 내에서 부모 클래스의 원본 메서드를 호출함
class Parent:
    def hello(self):
        print('부모 클래스의 hello 메서드')

class Child(Parent):
    def hello(self):
        super().hello()
        print('자식 클래스의 hello 메서드')
        
child = Child()
child.hello()
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.value)		# 10
print(child.child_value)	# 20

 

문제

아래 다중 상속 클래스의 출력을 예측해보자

class Base:
    def hello(self):
        print('Base의 hello()')                  # 7
        print('Base 클래스의 hello() 메서드')    # 8

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

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

class Child(A, B):
    def hello(self):
        print('Child의 hello()')                 # 1
        super().hello()                          # 2
        print('Child 클래스의 hello() 메서드')   # 11

child = Child()
child.hello()
Child.mro() # [__main__.Child, __main__.A, __main__.B, __main__.Base, object]  # -> 순서로 부모

 

'파이썬 > 파이썬 기초 문법' 카테고리의 다른 글

파이썬의 예외 처리  (0) 2024.10.20
파이썬 스페셜 메서드  (4) 2024.10.19
클로저와 데코레이터  (1) 2024.10.14
객체지향과 클래스  (0) 2024.10.14
파이썬 콜백 함수와 람다 함수  (1) 2024.10.07