- 
          
          TIL.33 클래스 상속(기반 클래스 및 파생클래스)TIL 2020. 11. 10. 20:51728x90반응형## 클래스 상속하기## 클래스 상속(inheritance) ## 상속이란 무언가를 물려준다는 뜻으로 클래스 상속은 기반 클래스(base class)에서 상속을 받아 새롭게 만드는 클래스를 파생 클래스(derived class)라 한다. ## 클래스 상속은 물려받은 기능을 유지한채로 다른 기능을 추가할 때 사용하는 기능이다. ## 보통 기반 클래스는 부모 클래스(parent class), 슈퍼 클래스(superclass)라고 부르고 ## 파생 클래스는 자식 클래스(child class), 서브 클래스(subclass)라고도 부른다.  ## 클래스 상속은 기반 클래스의 기능을 그대로 활용하면서 다른 기능을 추가할때 사용하는데, # 그렇다면 왜 굳이 클래스를 새로 만들지 않고 클래스 상슥을 시켜 파생 클래스를 만드는걸까? ## 만약에 새로운 기능이 필요할때마다 클래스를 새로 만들면 중복되는 부분을 반복해서 만드는 경우가 생긴다. # 예를들어 # 아래 그림에서 조류와 어류를 표현하고자 할때  # 생물이고, 동물이고, 척추동물이고 조류이다. 로 표현할때 # 생물이고, 동물이고, 척추동물이고 어류다. 처럼 불필요하게 반복을 만들어야하는데, ## 이럴때 상속을 이용하면 중복된 부분을 새로 만들지 않아 더 효율적이라 이해하자. class Person: def greeting(self): print('안녕') class Student (Person): def study (self): print('공부하기') james = Student() james.greeting() # 안녕 / # Student 클래스에는 greeting메서드가 없지만 Person의 파생클래스로서 # Person의 기능을 물려받는 상속을 해준 상태이므로 # Person에 있는 greeting메서드를 찾아가 정상 동작한다. james.study() # 공부하기 # Student 클래스에는 greeting 메서드가 없지만 # Person 클래스를 상속받았으므로 greeting 메서드를 호출할 수 있다.## 사람 클래스와로 학생 클래스 만들기 ## 이처럼 클래스 상속은 기반 클래스의 기능을 유지하면서 새로운 기능을 추가 할 수 있다. ## 특히 클래스 상속은 연관되면서 동등한 기능일 때 사용한다. ## 학생은 사람이므로 연관된 개념이고, 학생은 사람에서 역할만 확장되었을뿐 동등한 개념이다. 
 ## 클래스 상속 관계 확인하기. # 클래스의 상속 관계를 확인하고 싶을 때는 issubclass 함수를 사용한다. # 클래스가 기반 클래스의 파생 클래스인지 확인하여, 기반 클래스의 파생 클래스가 맞으면 True, 아니면 False를 반환합니다. # issubclass(파생클래스, 기반클래스) class Person: pass class Student(Person): pass print(issubclass(Student, Person)) :: True
 ## 상속 관계와 포함 관계 ## 상속 관계 class Person: def greeting(self): print('안녕하세요.') class Student(Person): def study(self): print('공부하기')# 앞에서 만든 Student 클래스는 Person 클래스를 상속받아 만들었다. ## 여기서, "학생은 사람이다"와 같이 학생 Student는 사람 Person이므로 같은 종류이다. ## 이처럼 상속은 명확하게 같은 종류이며 동등한 관계일 때 사용한다. 즉, "학생은 사람이다."라고 했을 때 말이 되면 동등한 관계이다. ## 상속관계는 영어로 "is a" 관계라고 부른다. (Student is a Persion) ## 포함 관계 ## 그렇다면 학생 클래스가 아닌 사람 목록을 관리하는 클래스를 만든다면 어떻게 해야 할까? # 다음과 같이 리스트 속성에 Person 인스턴스를 넣어서 관리하면 된다. class Person: def greeting(self): print('안녕하세요.') class PersonList: def __init__(self): self.person_list = [] # 리스트 속성에 Person 인스턴스를 넣어서 관리 def append_person(self, person): # 리스트 속성에 Person 인스턴스를 추가하는 함수 self.person_list.append(person)## 여기서는 상속을 사용하지 않고 속성에 인스턴스를 넣어서 관리하므로 PersonList가 Person을 포함하고 있다. ## 이러면 사람 목록 PersonList와 사람 Person은 동등한 관계가 아니라 포함 관계이다. ## 즉, "사람 목록은 사람을 가지고 있다."라고 말할 수 있으며, 포함 관계를 영어로 "has-a" 관계라고 부른다 (PersonList has a Person). ### 정리하자면 같은 종류에 동등한 관계일 때는 상속을 사용하고, 그 이외에는 속성에 인스턴스를 넣는 포함 방식을 사용하면 된다. 
 ## 기반 클래스의 속성 사용하기 # 다음과 같이 Person 클래스에 hello 속성이 있고, Person 클래스를 상속받아 Student 클래스를 만든다. # 그다음에 Student로 인스턴스를 만들고 hello 속성에 접근해보자. class Person: def __init__(self): print('Person __init__') self.hello = '안녕하세요.' class Student(Person): def __init__(self): print('Student __init__') self.school = '파이썬 코딩 도장' james = Student() print(james.school) print(james.hello) # 기반 클래스의 속성을 출력하려고 하면 error가 발생함## 기반 클래스의 기능을 물려받는다고 하였는데, 왜 기반 클래스의 hello 속성에 접근하지 못하는 걸까 ## 이유는 기반 클래스의 __init__메서드가 호출되지 않았기 때문이다 당연히 hello라는 속성이 만들어지지 못했기 때문이다. ## 즉, 기반 클래스 Person의 __init__ 메서드가 호출되지 않으면 self.hello = '안녕하세요.'도 실행되지 않아 속성이 만들어지지 않아 호출할 수 없다. ## super()로 기반 클래스 초기화하기 ## 위와 같이 기반 클래스의 __init__가 호출되지 않는 문제는 super()를 사용해서 기반 클래스의 __init__ 메서드를 호출해주면 된다. ### 즉, super()를 사용하면 기반 클래스의 메서드를 사용하겠다는 의미로 이해하자. # 다음과 같이 super() 뒤에 .(점)을 붙여서 메서드를 호출하는 방식이다. # super().메서드() class Person: def __init__(self): print('Person __init__') self.hello = '안녕하세요.' class Student(Person): def __init__(self): print('Student __init__') super().__init__() # super()로 기반 클래스의 __init__ 메서드 호출/ 위코드와 다른점 self.school = '파이썬 코딩 도장' james = Student() print(james.school) print(james.hello) 기반 클래스 Person 의 속성 hello 를 찾는 과정 # 실행을 해보면 기반 클래스 Person의 속성인 hello가 잘 출력된다. ## super().__init__()와 같이 기반 클래스 Person의 __init__ 메서드를 호출해주면 기반 클래스가 초기화되어서 속성이 만들어진다고 한다. # (기반 클래스를 초기화된다는 말이 이해가 가질 않는다 - 질문) # 실행 결과를 보면 'Student __init__'과 'Person __init__'이 모두 출력된다. ## 여기서 print를 각 사용하였을때의 결과이다. james = Student() print(james.school) # Student __init__ Person __init__ 파이썬 코딩 도장 print(james.hello) # Student __init__ Person __init__ 안녕하세요. print(james.school) print(james.hello) # Student __init__ Person __init__ 파이썬 코딩 도장 안녕하세요.## print를 2번 연속사용하면 Student와 Person의 메서드가 "한번씩만" 호출되어 결과가 나오는것으로 생각한다. ## 기반 클래스를 초기화하지 않아도 되는 경우 (super() 사용하지 않는방법) class Person: def __init__(self): print('Person __init__') self.hello = '안녕하세요.' class Student(Person): pass james = Student() print(james.hello) # Person __init__ 안녕하세요.## 이처럼 파생 클래스의 __init__메서드가 없다면 ## 기반 클래스의 __init__이 자동으로 호출되므로 기반 클래스의 속성을 사용할 수 있다. ## 좀더 명확하게 super 사용하기 ## super는 다음과 같이 파생 클래스와 self를 넣어서 현재 클래스가 어떤 클래스인지 명확하게 표시하는 방법도 있다. # 물론 super()와 기능은 같다. # super(파생클래스, self).메서드 class Student(Person): def __init__(self): print('Student __init__') super(Student, self).__init__() # super(파생클래스, self)로 기반 클래스의 메서드 호출 self.school = '파이썬 코딩 도장'728x90반응형'TIL' 카테고리의 다른 글TIL.35 두점 사이의 거리 구하기 (0) 2020.11.12 TIL.34 클래스 상속(오버라이딩 및 추상클래스) (0) 2020.11.11 TIL.32 클래스의 속성과 메서드 (0) 2020.11.09 TIL. 31 클래스의 속성, 비공개 속성 사용하기 (0) 2020.11.08 TIL.30 클래스와 메서드 사용하기 (0) 2020.11.07