파이썬 기본 문법7(상속)

파이썬 기본문법 시리즈 7편입니다.

다른 파이썬 기본문법 시리즈는

상속

정의

  • class 기반 클래스: #멤버 정의
  • class 파생클래스(기반클래스):
    • 아무 멤버를 정의하지 않아도 기반 클래스의 모든 것을 물려받아 갖게 됨.
    • 단, private 멤버(__ 로 시작되는 이름을 갖는 멤버)는 제외.
class Base:
  def __init__(self):
    print(self)
    self.message = "Hello, World"

  def print_message(self):
    print(self.message)

class Derived(Base):
  pass

if __name__ == '__main__':
  base = Base()
  base.print_message()

  a = Derived()
  a.print_message()

위의 코드를 보시면 Derived(Base)를 통해 상속을 받고 main에서 pass를 적었음에도 불구하고 Base의 함수를 쓰고 있는 것을 볼 수 있습니다.


다형성

  • 여러가지 형태를 가질 수 있는 능력
# 다형성(Polymorphism)
class ArmorSuite:
  def armor(self):
    print('armored.')

class IronMan(ArmorSuite):
  pass

def get_armored(suite):
  suite.armor()

if __name__ == '__main__':
  suite = ArmorSuite()
  get_armored(suite)

  iron_man = IronMan()
  get_armored(iron_man)

위의 코드를 보면 IronMan에서 상속을 받아서 다른 클래스지만 같은 결과값을 가져오는 것을 알수 있다.

같은 모양의 코드가 다른 기능을 하는것이 다형성이다.


super()

  • 부모클래스의 객체 역할을 하는 프록시(Proxy)를 반환하는 내장 함수.
class A:
    def __init__(self):
        print("A.__init__()")
        self.message = "Hello"

class B(A):
    def __init__(self):
        super().__init__()      #A.__init__(self)
        print("B.__init__()")

        print("self.message is "+ self.message)

if __name__ =="__main__":
    obj = B()

    print(obj.message)

위의 코드를 보면 self.message가 생성자에 있는데 A 클래스를 생성하지않아서 B에서 생성을 해서 사용하는 것을 볼수 있다.

클래스가 생성되지 않으면 self.message가 생성이 되지 않는다는 것을 알 수 있다.


다중 상속

  • 자식클래스 하나가 여러 부모 클래스로부터 상속받는 것.
class A:
  pass

class B:
  pass

class C:
  pass

class D(A,B,C):
  pass

만약 A에 있는 함수가 B에도 똑같은 이름의 함수가 있다면 매개변수에서 앞에 있는 A의 함수를 사용하게 된다.


오버라이딩

  • 부모클래스로 부터 상속받은 메서드를 다시 자식 클래스에 정의하는것
class A:
  def message(self):
    print("A")

class B(A):
  def message(self):
    print("B")

if __name__=='__main__':
  B().message()

위의 코드의 답은 B가 나온다. 똑같은 이름의 message를 상속받지만 오버라이딩하면서 A의 기능에서 변경해서 사용했다.


데코레이터

  • 함수를 꾸미는 객체
  • __call__() 메서드를 구현하는 클래스
    • 객체를 함수 호출 방식으로 사용하게 만드는 메서드
class Callable:
    def __call__(self):
        print("I am called")

if __name__ == '__main__':
    obj = Callable()
    obj()

위의 코드를 보면 obj()를 볼수 있는데 obj()를 부르면 call의 메서드를 부르게 된다.

응용)

class MyDecorator:
    def __init__(self, f):
        print("Initializing MyDecorator...")
        self.func = f #MyDecorator의 func 데이터 속성이 print_hello를 받아둠.

    def __call__(self):
        print("Begin:{0}".format(self.func.__name__))

        self.func() # __call()__ 메서드가 호출되면 생성자에서 저장해둔 함수

        print("End:{0}".format(self.func.__name__))

def print_hello():
        print("Hello")

if __name__=='__main__':
    print_hello2 = MyDecorator(print_hello)

    print_hello2()
class MyDecorator:
    def __init__(self, f):
        print("Initializing MyDecorator...")
        self.func= f

    def __call__(self):
        print("Begin:{0}".format(self.func.__name__))
        self.func()
        print("End:{0}".format(self.func.__name__))

@MyDecorator
def print_hello():
    print("hello!!!!")

if __name__ == '__main__':
    print_hello()

위 코드에서는 일반 코드이고 밑에 코드는 @데코레이션을 사용한 코드입니다. 보시면 간결해지신것을 보실수 있습니다.

두개다 같은 Initializing MyDecorator...
Begin:print_hello
hello!!!!
End:print_hello
가 나오게 됩니다.


for문 순회 가능 객체 만들기 예)

  • list
    list = [1, 2, 3]
    for e in list:
    print(e)
    
  • iterator()
iterator = range(3).__iter__() print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) # error

위의 코드를 보면 이터레이터는 없는 인덱스값을 찾으면 오류가 걸리는 것을 알수 있다.

  • 제너레이터(Generator)
def generator():
    yield 0 # __iterator__가 생성된다고 생각을 하면 된다.
    yield 1
    yield 2
    yield 3

iterator = generator()
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())

위의 코드를 보면 yield가 이터레이터 인덱스 갯수를 하나 늘려준다고 생각을하면 된다.

그러면서 뒤에있는 숫자값을 넣어줘서 인데스0번은 0의 값을 가지게 된다.


상속의 조건 : 추상 기반 클래스

  • 자식 클래스가 갖춰야 할 특징(메서드)을 강제하는 기능.
  • 강제 조건 규약에 따르지 않으면 TypeError 예외 발생.
  • metaclass = ABCMeta 클래스와 @abstractmethod 데코레이터를 이용
from abc import ABCMeta
from abc import abstractmethod

class AbstractDuck(metaclass=ABCMeta):
    @abstractmethod
    def Quack(self):
        pass

class Duck(AbstractDuck):
    def Quack(self):
        print("[Duck] Quack")

if __name__=='__main__':
    duck = Duck()
    duck.Quack()

위의 코드를 보면 AbstractDuck(metaclass=ABCMeta)를 볼수 있다. metaclass=ABCMeta와 @abstractmethod를 이용하면 강제성을 지닐 수 있다.

다른 파이썬 기본문법 시리즈는

Categories:

Updated:

Leave a comment