TIL(2020.07.29)

Awesome·2020년 7월 29일
0

TIL

목록 보기
19/46
post-custom-banner

객체지향 프로그래밍(Object Oriented Programming)(2)

특징

객체지향 프로그래밍의 4가지 특징에 대해 알아본다.

3.상속

두 클래스 사이의 부모-자식 관계를 설정하는 것

  • mro(method resolution order) 함수를 통해 클래스의 상속관계가 리스트로 반환됨 (class.mro())
  • isinstance(인스턴스, 클래스) : 인스턴스가 클래스에 속해있는지 여부를 Boolean으로 반환
    • 자식 클래스의 인스턴스는 부모 클래스의 인스턴스이기도 함!(다형성)
  • issubclass(자식클래스, 부모클래스) : 첫 번째 인자 클래스가 두 번째 인자의 자식 클래스인지 여부 반환

오버라이딩(overriding)

부모 클래스로부터 상속 받은 것을 자식 클래스의 특성에 맞게 변환하는 것

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
class Man(Person):
    def __init__(self, name, age, gender):
        Person.__init__(self, name, age)
        self.gender = gender
        
# super()
class Woman(Person):
    def __init__(self, name, age, gender):
        super().__init__(name, age)
        self.gender = gender

super() 를 통해서 부모 클래스의 속성을 그래도 사용할 수 있다. 이 때, self 파라미터는 포함하지 않는다.

부모 클래스의 클래스 속성을 오버라이딩 하면 자식 클래스에 선언된 값을 사용할 수 있다. 이는 우선순위가 자식 클래스에 있기 때문이다. mro 함수를 써보면, 자식클래스가 가장 앞에 나온다. 따라서 오버라이딩 했을 때도 자식 클래스의 메소드나 속성 값을 우선적으로 찾는다는 것을 뜻한다.

다중상속

두 개 이상의 부모 클래스로부터 상속 받는 경우를 말한다.
__init__ 함수에서 super() 를 사용하는 경우, 어떤 부모 클래스인지가 불명확하다는 단점이 있으므로, 해당 부모 클래스로부터 직접 상속받는 방법을 사용하는 것이 좋다.

class Programmer:
    def __init__(self, language):
        self.language = language
    def prefer_language(self):
        print(f"He prefers to coding with {self.language}")
        
class Hobby:
    def __init__(self, team):
        self.team = team
    def prefer_team(self):
        print(f"He's favorite team is {self.team}")
        
class Person(Programmer, Hobby):
    def __init__(self, language, team, age):
        Programmer.__init__(self, language)
        Hobby.__init__(self, team)
        self.age = age

kwon = Person("python","Chelsea", 31)
kwon.prefer_language()
kwon.prefer_team()

> He prefers to coding with python
> He's favorite team is chelsea

다중 상속의 경우, 메서드를 오버라이딩하는 것이 혼란을 발생시키지 않는 방법이다. 그렇지 않는다면, 다중 상속 시에 상속 순서에 따라서 앞에 오는 부모 클래스가 우선 순위로 상속받는다.

4.다형성

한 변수가 A 클래스의 인스턴스와 B 클래스의 인스턴스 둘 다 될 수 있는 성질

다형성을 활용하는 데에 있어서 상속은 매우 유용한 성질이다. 모든 클래스가 공통의 성질이나 메서드를 가지는 것은 아니기 때문에 공통된 속성을 갖는 부모 클래스를 생성하는 것이 매우 효율적이다. 이 때, 부모 클래스는 메서드의 목록만을 나열한다. 이는 자식 클래스에서 메서드의 구현(오버라이딩)을 강제하기 위함이다.

추상 클래스

다형성의 특성을 활용하기 위해 메서드를 나열하기 위한 부모 클래스를 생성할 때, 이를 추상 클래스라고 한다.
abc 라이브러리의 ABC(Abstract Bass Class), abstractmethod를 활용한다.

from abc import ABC, abstractmethod
 
class StudentBase(ABC):
    @abstractmethod
    def study(self) -> str:
        pass
 
    @abstractmethod
    def go_to_school(self) -> str:
        pass
 
class Student(StudentBase):
    def study(self):
        print('공부하기')
 
james = Student()
james.study()

추상 클래스는 인스턴스를 생성할 수 없다. 추상 클래스의 목적이 여러 자식 클래스가 공통으로 갖는 메서드나 속성을 사전에 나열하기 위함이므로 실질적인 기능은 없으며, 인스턴스로 불러올 이유도 없다.

++ type hinting 을 더해 추상 클래스의 결과 값에 대한 타입을 명시할 수 있다.
++ 추상화에 대해 알아둘 점

  1. 추상 클래스는 추상화의 한 예시이다.
    • 추상 클래스는 서로 관련있는 클래스들의 공통 부분을 묶어서 추상화하는 것으로 볼 수 있다.
  2. 추상 클래스에도 일반 메소드를 추가할 수 있다.
    • 자식 클래스가 물려받아 그대로 사용하거나 오버라이딩하여 사용할 수 있다.
  3. 추상 메소드에도 내용을 채울 수 있다.
    • docstring, print문 등의 내용을 채울 수 있고, 자식 클래스에서 super 함수로 상속받아 오버라이딩 할 수 있다.
  4. 자식 클래스가 특정 변수를 갖도록 유도할 수 있다.
@property
@abstractmethod
def x(self):
    """도형의 x 좌표 getter 메소드"""
    pass

@property
def x(self):
    """_x getter 메소드"""
    return self._x

@x.setter
def x(self, value):
    """_x setter 메소드"""
    self._x = value

위와 같이 앞서 배운 property decorator를 사용하여 getter method를 설정하면, getter method를 오버라이딩하지 않을 경우 발생하는 에러를 피하기 위해서 반드시 지정해줘야 한다.

++ 추상 클래스의 다중 상속
추상 클래스의 다중 상속의 경우 메서드 이름이 중복되더라도 큰 문제가 없다. 그 이유는 추상 클래스를 상속받은 자식 클래스는 어차피 추상 메서드를 오버라이딩해야하기 때문에 겹쳐도 전혀 문제가 없다. 하지만 일반 메서드는 추상 클래스라고 할 지라도 일반 클래스와 같은 문제가 발생한다.

함수/메서드 다형성

파이썬 함수에 대해 공부할 때 정리했던 위치별 인자의 종류(위치 인자, 가변 위치인자, 키워드 인자 등)가 달랐던 점이 바로 함수 혹은 메서드의 다형성이다. 여러 형태로 결과 값을 호출하는 것을 의미한다.

파이썬 코딩 스타일과 다형성

  • 파이썬 코딩 스타일
  1. LBYL (Look Before You Leap) : 어떤 작업을 수행하기 전에 미리 확인하는 스타일
  2. EAFP (Easier to Ask for Forgiveness than Permission) : 일단 실행하고, 문제가 생기면 처리한다. (파이썬)

예를 들어, 어떠한 메서드에 대한 인자가 반드시 상위 클래스의 인스턴스여야 하는 경우에

if isinstance(instance, Class):
    return pass

와 같이 인스턴스를 확인하는 절차를 거치는 것이 아니라, 일단 모든 인자를 받아들이고 나중에 try/except 문 을 활용해 처리하는 것이 EAFP 스타일이다.

profile
keep calm and carry on
post-custom-banner

0개의 댓글