ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코딩도장] day26. 파이썬 클래스 상속 사용하기(2/2) - object클래스, 다중 상속, 추상 클래스
    IT/파이썬 2020. 9. 19. 22:58

    출처 : unsplash

    ■ 들어가기

    - 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그


    ▶ Unit36. 클래스 상속 사용하기

         - 36.1 사람 클래스로 학생 클래스 만들기

         - 36.2 상속 관계와 포함 관계 알아보기

         - 36.3 기반 클래스의 속성 사용하기

         - 36.4 메서드 오버라이딩 사용하기

         - 36.5 다중 상속 사용하기

         - 36.6 추상 클래스 사용하기

     

    >> 36.5 다중 상속 사용하기 <<

    - 다중 상속 : 여러 기반 클래스로부터 상속을 받아서 파생 클래스를 만드는 방법

    - 클래스 생성 시 ()(괄호) 안에 클래스 이름을 ,(콤마)로 구분해서 생성

    - 사용법
    class 기반클래스이름1 :
        코드

    class 기반클래스이름2 :
        코드

    class 파생클래스이름(기반클래스이름1, 기반클래스이름2) :
        코드
    소스 (class_multiple_inheritance.py) 결과
    class Person :
        def greeting(self) :
            print('안녕하세요.')

    class University :
        def manage_credit(self) :
            print('학점 관리')

    class Undergraduate(Person, University) :
        def study(self) :
            print('공부하기')


    james = Undergraduate()
    james.greeting()        # 기반 클래스 Person의 메서드 호출
    james.manage_credit()   # 기반 클래스 University의 메서드 호출
    james.study()           # 파생 클래스 Undergraduate에 추가한 study 메서드
    안녕하세요.
    학점 관리
    공부하기

    - Person, University, Undergraduate 클래스의 관계

    출처 : 파이썬 코딩 도장 (dojang.io)

     

    1. 다이아몬드 상속

    - 클래스 간의 관계가 다이아몬드 같이 생긴 관계

    출처 : 파이썬 코딩 도장 (dojang.io)

    - A, B, C 클래스 모두 greeting이라는 같은 메서드를 가지고 있는 경우, D는 어떤 클래스의 메서드를 호출해야할지 애매하다.

    - 어떨 때는 A의 메서드를 호출하고, 어떨 때는 B 또는 C의 메서드를 호출하는 것과 같은 경우 문제가 많아 "죽음의 다이아몬드"라 불리기도 함

    소스 (class_diamond_inheritance.py) 결과
    class A :
        def greeting(self) :
            print('안녕하세요. A입니다.')

    class B(A) :
        def greeting(self) :
            print('안녕하세요. B입니다.')

    class C(A) :
        def greeting(self) :
            print('안녕하세요. C입니다.')

    class D(B, C) :
        pass


    x = D()
    x.greeting()
    안녕하세요. B입니다.

     

    2. 메서드 탐색 순서 확인하기

    √ 그런데 항상 B의 메서드를 호출하는거 같은데...??

    - 메서드 호출 시 인접한 클래스에서부터 찾게 되며, D는 B, C로부터 상속을 받았기 때문에 메서드 조회 시 B클래스부터 찾아서 사용하므로 B의 greeting메서드 "안녕하세요. B입니다."가 반환된다.

    - 만약 D가 C, B로부터 상속 받는 것으로 설정된다면 항상 C의 greeting을 우선 반환함

    - 위와 같은 다이아몬드 상속에 대한 문제 해결을 위해 파이썬에서는 메서드 탐색 순서(Method Resolution Order, MRO)를 제공

    - 사용법 : 클래스.mro()
    class A : 
        def greeting(self) : 
            print('안녕하세요. A입니다.') 

    class B(A) : 
        def greeting(self) : 
            print('안녕하세요. B입니다.') 

    class C(A) : 
        def greeting(self) : 
            print('안녕하세요. C입니다.') 

    class D(C, B) : 
        pass 


    x = D() 
    x.greeting()
    안녕하세요. C입니다.

    - MRO를 확인하면 메서드 호출 순서는 1) 자기 자신 2) 다중 상속 시 기반클래스 왼쪽부터 오른쪽 순서

    >>> D.mro()
    [<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

    [참고] object 클래스

    - 파이썬에서 object는 모든 클래스의 조상

    - 모든 클래스는 object 클래스를 상속 받으므로 기본적으로 object를 생략함

    >>> int.mro()
    [<class 'int'>, <class 'object'>]
    >>> class X :
                  pass
    >>> class X(object) :   # 위의 생성 방법과 동일
                  pass

    >> 36.6 추상 클래스 사용하기 <<

    - 추상 클래스(abstract class) : 메서드의 목록만 가진 클래스로 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용

    - 추상 클래스 만드려면 import로 abc 모듈을 가져와야 함 (abc = abstract base class)

    - 클래스의 ()(괄호) 안에 metaclass=ABCMeta를 지정하고,

      메서드를 만들 때 위에 @abstractmethod를 붙혀 추상 메서드 지정

    - 사용법
    from abc import *

    class 추상클래스이름(metaclass=ABCMeta) :
        @abstractmethod
        def 메서드이름(self) :
            코드
    소스 (class_abc_error.py) 결과
    from abc import *

    class StudentBase(metaclass=ABCMeta) :
        @abstractmethod
        def study(self) :
            pass

        @abstractmethod
        def go_to_school(self) :
            pass


    class Student(StudentBase) :
        def study(self) :
            print('공부하기')


    james = Student()
    james.study()
    Traceback (most recent call last):
      File "C:/project/class_abc_error.py", line 18, in <module>
        james = Student()
    TypeError: Can't instantiate abstract class Student with abstract methods go_to_school

    - StudentBase를 상속받은 Student에서 추상 클래스 go_to_school을 구현하지 않아 TypeError 발생!

    - 추상 클래스를 상속받을 경우 @abstractmethod가 붙은 추상 메서드는 모두 구현해야 함!

    소스 (class_abc.py) 결과
    from abc import *

    class StudentBase(metaclass=ABCMeta) :
        @abstractmethod
        def study(self) :
            pass

        @abstractmethod
        def go_to_school(self) :
            pass


    class Student(StudentBase) :
        def study(self) :
            print('공부하기')

        def go_to_school(sefl) :
            print('학교가기')


    james = Student()
    james.study()
    james.go_to_school()
    공부하기
    학교가기

    - 추상 메서드는 호출할 일이 없으므로 빈 메서드로 만듦 (코드에 pass 처리)

     

     

    ● 요약
    1. 추상 클래스 : 인스턴스 생성 시 사용하지 않으며, 오직 상속시에만 사용!
    2. 추상 메서드 : 추상 클래스는 인스턴스를 생성할 수 없으므로 추상 메서드도 호출할 일이 없어 빈 메서드(pass)만 생성
    3. 다중 상속 시 메서드 호출 순서는 1) 자기 자신 2) 기반 클래스 호출 순서(왼쪽에서 오른쪽) 대로 호출

     

    댓글

Designed by Tistory.