KDT_4기 파이썬 기초 0927(3)
2024.09.27 수업 내용 복습일기 세번째
오늘은 파이썬의 상속에 대해 알아보자
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)
#Animal 클래스를 상속받았기 때문에 Animal클래스의 생성자
#매개변수를 전달해야함
class Dog(Animal):
pass
Rucy = Dog('루시',14)
Rucy.eat('사료')
Rucy.sleep(12)
2. 클래스 상속 시 생성자 호출 순서
- 자식 클래스(child class)의 생성자가 호출됩니다.
- 자식 클래스의 생성자에서 부모 클래스(parent class)의 생성자를 호출해야 합니다. 이를 위해 super() 함수를 사용합니다. super() 함수는 현재 클래스의 부모 클래스를 참조하며, 부모 클래스의 생성자를 호출할 수 있습니다.
- 부모 클래스의 생성자가 호출됩니다.
- 부모 클래스의 생성자가 실행을 마치면 자식 클래스의 생성자로 돌아가 자식 클래스의 생성자 코드가 실행됩니다.
class Parent:
def __init__(self):
print('부모 클래스 생성자 호출')
class Child(Parent):
def __init__(self):
print('자식 클래스 생성자 호출')
super().__init__()
print('모든 생성자 호출 완료')
child = Child()
3. Object 클래스
Object 클래스는 파이썬에서 모든 클래스의 부모 클래스 역할을 하는 기본 클래스입니다. 파이썬에서 정의하는 모든 클래스는 자동으로 Object 클래스를 상속받습니다. 이를 통해 파이썬의 모든 객체는 Object 클래스에서 제공하는 기본적인 동작과 메서드를 사용할 수 있게 됩니다. 예를들어 __ str__(), __ 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 Dog(Animal):
def run (self):
print(f'{self.name}달립니다')
Rucy = Dog('루시',14)
Rucy.eat('사료')
Rucy.sleep(12)
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 eat(self,name,food):
# print(f'{name} {food} 아주 맛있게 먹습니다') 자바와 같은 오버로딩 개념이 없다는 점 유의
def superEat (self,food):
super().eat(food)
Rucy = Dog('루시',14)
Rucy.eat('사료')
Rucy.sleep(12)
Rucy.run()
Rucy.superEat('사료')
animal = Animal('동물',10)
animal.eat('먹이')
animal.sleep(10)
#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 Kim(Animal,Human):
pass
kim = Kim('김사과',20)
kim.eat('밥')
kim.study(2)
kim.sleep(8)
print(Kim.mro())#중복된 메소드 있을때 더 상위에 있는 메소드를 적용하게 되어있음
>>>결과
[<class '__main__.Kim'>, <class '__main__.Animal'>, <class '__main__.Human'>, <class 'object'>]
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):#Human class의 def sleep(8)을 호출하기 위해서
Animal.__init__(self,name,age)
Human.__init__(self,name,age,height)
#super()메소드로 부모클래스 호출 시 mro에 의해 또 Animal호출되기 때문에 해당 클래스 명으로 직접 호출한다
def sleep(self,hour):
Human.sleep(self,hour)
kim = Kim('김사과',20)
kim.eat('밥')
kim.study(2)
kim.sleep(8)#height를 받지 않았지만 mro에 의해서 크게 문제되지 않음
kim = Kim('김사과',20,170)
kim.eat('밥')
kim.study(2)
kim.sleep(8)
6. super() 함수
super()는 파이썬의 내장 함수로서, 상속과 관련된 작업을 수행할 때 사용됩니다. 특히, 자식 클래스에서 부모 클래스의 메서드를 호출할 때 사용됩니다. 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)
print(child.child_value)
문제1
- 아래의 다중상속 클래스의 출력이 어떻게 되는지 예측해보자
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.head()
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()#부모 1.A >>
print('Child 클래스의 hello() 메서드')
상속의 순서를 mro()를 통해 출력하면 아래의 답이 이해된다
Child.mro()
'''
자식 클래스가 항상 부모클래스보다 먼저 온다
부모 클래스들은 상속된 순서대로 나타난다
충돌을 해결할 떄는 왼쪽에 있는 부모 클래스의 순서를 우선시한다
Child의 hello()
A의 hello()
B의 hello()
Base의 hello()
Base 클래스의 hello()메서드
B 클래스의 hello()메서드
A 클래스의 hello()메서드
Child 클래스의 hello() 메서드
'''
child = Child()
child.hello()
'인공지능 > 파이썬 기초' 카테고리의 다른 글
파이썬의 예외 처리 (0) | 2024.10.01 |
---|---|
스페셜 메서드 (0) | 2024.10.01 |
클로저와 데코레이터 (0) | 2024.10.01 |
객체지향과 클래스 (4) | 2024.10.01 |
콜백함수와 람다함수 (0) | 2024.09.30 |