2018년 11월 20일 화요일

[공부]python에서 class 상속

<참고: http://schoolofweb.net/blog/posts/%ED%8C%8C%EC%9D%B4%EC%8D%AC-oop-part-5-%EC%83%81%EC%86%8D%EA%B3%BC-%EC%84%9C%EB%B8%8C-%ED%81%B4%EB%9E%98%EC%8A%A4inheritance-and-subclass>

class와 inherit(상속)은 Dont' Repeat Yourself (불필요하게 같은 코드를 반복하는 것을 막자) 가 목적.

목적: 기본 클래스(예: Fruit)와 그 서브클래스(예: Apple, Banana)가 있는 경우는 기본 클래스(공통 속성)-서브클래스(개별 속성)로 가는 것이 유지/관리측면에서 좋음.

Fruit과 Apple을 만듬.
class Fruit(object):
    def __init__(self, color):
        self.name = self.__class__.__name__        self.color = color

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))

class Apple(Fruit):
    pass
if __name__ == '__main__':
    apple_1 = Apple('green')
    apple_1.show_status()
    help(Apple)
 # class Apple에서 __init__찾음. 없으니 부모 class인 Fruit에서 __init__찾아서 실행.
name: Apple
color: green

class Apple의 초기화 함수에 Size를 추가해보자.
바보같은 사용법
class Fruit(object):
    def __init__(self, color):
        self.name = self.__class__.__name__        self.color = color

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))

class Apple(Fruit):
    def __init__(self, color, size):
        self.name = self.__class__.__name__        self.color = color
        self.size = size

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))
        print('size: {}'.format(self.size))

if __name__ == '__main__':
    apple_1 = Apple('green', 30)
    apple_1.show_status()
    help(Apple)
목적은 달성했으나, Fruit에 있는 코드들(name, color)이 반복됨. 

멍청한 사용법
class Fruit(object):
    def __init__(self, color):
        self.name = self.__class__.__name__        self.color = color

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))

class Apple(Fruit):
    def __init__(self, color, size):
        Fruit.name = self.__class__.__name__        Fruit.color = color
        self.size = size

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))
        print('size: {}'.format(self.size))

if __name__ == '__main__':
    apple_1 = Apple('green', 30)
    apple_1.show_status()
    help(Apple)

    apple_2 = Apple('red', 10)
    apple_2.show_status()

    apple_1.show_status()
class의 instance가 아닌 class에 값을 대입함.
apple_1의 값 변경은 apple_2의 값도 바뀜. --> 의도하지 않은 결과.

이 경우는 super()함수를 이용하여 부모 클래스의 도움을 받아야 함.

올바른 사용법
class Fruit(object):
    def __init__(self, color):
        self.name = self.__class__.__name__        self.color = color

    def show_status(self):
        print('name: {}'.format(self.name))
        print('color: {}'.format(self.color))

class Apple(Fruit):
    def __init__(self, color, size):
        super(Apple, self).__init__(color)
        self.size = size

    def show_status(self):
        super(Apple, self).show_status()
        print('size: {}'.format(self.size))

if __name__ == '__main__':
    apple_1 = Apple('green', 30)
    apple_1.show_status()
    help(Apple)

위와 같이 사용하면 중복된 코드를 방지할 수 있다.

help(Apple) # Apple class가 이름을 찾는 순서를 보여줌(자기 클래스 namespace, 부모 클래스 namespace, 내장 object namespace).