[플레이데이터 빅데이터 부트캠프]Python 클래스(3)

매직 메소드

  • 특별한 의미를 가지고 있는 미리 정의된 메소드들이다.
  • 메소드 이름 앞뒤에 _가 붙어있는 메소드
  • 던더 메소드라고도 한다.(던더는 더블 언더의 준말이다.)

생성자

  • Constructor : __init__
  • 객체가 생성될 때, 인터프리터에 의해서 자동으로 호출되는 메소드
  • 객체변수의 초기화
    • 객체가 생성될 때 모든 만들어질 객체가 기본으로 이정도는 동일한 속성으로 가지고 가게 하고 싶다면
        • 객체가 실행될 때
        • 생성자가 실행된다는 것 객체가 갓 만들어졌다 라는 것을 의미합니다.
        • 생성자를 통해 객체변수에 초기화할 수 있다.

실습

  • 생성자에 이름, 나이를 같이 입력받아야 인스턴스가 생성되도록 수정해주시고,
  •  __add__라는 던더메소드를 둘의 이름과 나이의 합을 출력하는 메서드로 변경해주세요.
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.nation = 'Korea'

    def __add__(self, other):
        print(self.name, other.name)
        print(self.age + other.age)
    
우영우 = Person('우영우', 27)
이준호 = Person('이준호', 27)

우영우 + 이준호
우영우 이준호
54

StaticMethod / ClassMethod

  • StaticMethod : 한 번 만들어놓으면 자식 클래스에서도 같은 방식으로 동작한다.
  • ClassMethod : 해당 클래스에 맞게 메서드가 자식 클래스를 참조하여 동작한다.
class Person:
    nation = 'Korea'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def method(self, a, b):
        return a+b

    @staticmethod
    def method1():
        return Person.nation

    @classmethod
    def method2(cls):
        print('cls', cls)
        return cls.nation

위의 코드에서 method1은 Staticmethod, method2는 Classmethod를 가리킨다.

class Student(Person):
	nation = '북조선'
    
여성민 = Student('여성민', 22)

여성민.method1()
'Korea'

여성민.method2()
cls <class '__main__.Student'>
'북조선'

클래스의 특징

은닉성

- 클래스 안에 있어서 인스턴스로는 확인할 수 없게 보호하는 장치
    - 외부에서 참조 불가하게 비공개화
    - 공개하고 싶지 않은 속성(기능) 이름 앞에 _를 붙이도록 약속하고 있다.
    - 이름 앞에 _언더바가 붙어있으면 참조하지 않음. 해당 클래스 안에서만 씀. 이라고 약속한다.

맹글링( __)

  •  클래스의 속성값을 외부에서 접근하기 힘들게 할 때
  •  하위 클래스가 상위 클래스의 속성을 오버라이딩(덮어쓰기) 하는 것을 막을 때 사용한다.
class BankAccount:
    def __init__(self, 아이디, 비번, 계좌번호, 잔고):
        self.__아이디 = 아이디
        self.__비번 = 비번
        self.__계좌번호 = 계좌번호
        self.__잔고 = 잔고

    @property
    def check_pw(self): # 값을 가지고만 오는 함수 getter
        return self.__비번

    @check_pw.setter
    def check_pw(self, 새비번): # 값을 변경만 하는 함수 setter
        if isinstance(새비번, str):
            self.__비번 = 새비번
        else:
             print('문자열로 입력하세욧!')
  • 위의 코드와 같이 은행계좌와 같이 민감한 개인정보에 관한 클래스에서는, 맹글링을 사용해서 클래스의 속성을 은닉해준다.
  • 그리고 getter와 setter를 사용하여 메소드를 변수처럼 불러오고 수정할 수 있다.
  • getter(@property)는 값을 불러오는 함수이고, setter(@함수명.setter)는 값을 변경하는 함수이다.

상속

  • 클래스의 재사용성을 확대한 개념
    • 잘 정의된 클래스가 있으면 다시 물려받아서 그대로 재사용
  • 상속을 이용하면 클래스가 점점 확장
    • 모든 학생은 사람 o
    • 모든 사람은 학생 x
    • is-a (Student is a Person)
      • 학생은 사람이니까 사람이 갖는 속성이나 기능을 동일하게 사용할 수 있다.
      • 학생 클래스를 만들 때 새로 정의하지 말고 사람 클래스를 물려받아서(상속받아서) 그대로 사용하고 나머지 추가 학생의 속성, 기능만 구현해주면 편하다.
class Student(Person): 
    def __init__(self, name, age, studyhour):
        super().__init__(name, age) # super().__init__()  - 부모 클래스의 생성자를 그대로 가져오는 역할을 한거고요
                                    # super()는 부모와 자식 클래스 사이에 속성, 함수 등을 물려주는 역할
        self.studyhour = studyhour

    def method(self):
        super().method()
        print('자식 클래스에서 실행된 메소드입니다')

    @property # 은닉성을 담보로 하면서 해당 내용을 보여주기 위한 우회 접근 데코레이터 - 이 덕분에 함수()인데 변수처럼 호출됨
    def outer_name(self):
        return self._name

    @outer_name.setter # setter를 위한 데코레이터 
    def outer_name(self, name): 
        print(self._name, name, '으로 자식클래스에서 호출했습니다') # 부모에 있는 함수에 실행문을 추가
        super()
        
    def print_hour(self): # 부모에는 없는 함수(기능)을 추가
        print(f'{self.outer_name}님은 오늘 {self.studyhour}만큼 공부하셨습니다.')
  • Student 클래스는 위의 Person 클래스를 상속받은 클래스이다.
  • 즉 학생은 사람이기 때문에, 사람의 속성을 그대로 물려받아서 클래스를 만들면 편하다.
  • super()를 사용하여 부모 클래스의 속성과, 함수를 가지고 올 수 있다.
신짱구 = Student('신짱구', 13, 8)

신짱구.outer_name = '훈이'
신짱구 훈이 으로 자식클래스에서 호출했습니다

신짱구.print_hour()
훈이님은 오늘 8만큼 공부하셨습니다.

다형성

오버로딩

  •  클래스 내의 하나의 메소드가 여러개의 기능을 처리
  • 파이썬은 오버로딩이 안 된다.
  • 연산자 오버로딩이라고 매직 메소드를 이용해서 눈속임

오버라이딩

  • 메소드를 재정의(덮어쓴다)
  • 메소드 뿐 아니라 속성도 오버라이팅
  • 부모한테 물려받은 메소드를 그대로 사용하지 않겠다는 의미
  • 상속이 되어야만 재정의 할 수 있다.
  • 상속받은 메소드와 동일한 이름이어야 한다 .

생성자 오버라이딩

  • 자식클래스에서 추가해야 할 속성이 있는 경우
  • 부모 클래스에서 물려받아 일부 변경 가능하다.
class Student(Person): 
    def __init__(self, name, age, studyhour):
        super().__init__(name, age)
                                    
        self.studyhour = studyhour
        
훈이 = Person('훈이', 13)
훈이 = Student('훈이', 13, 8)