ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 클래스
    언어/파이썬 & 장고 2016. 10. 7. 13:50

    __init__() 메소드를 사용한 초기화

    클래스의 생성자가 호출되면 가장 먼저 __new__() 메소드가 호출됩니다. 이 메소드는 클래스의 인스턴스를 만듭니다. 이 메소드가 호출된 다음 __init__()메소드를 호출하게 됩니다.

    보통 변수 선언은 __init__()에서 담당하지만 클래스에 직접 정의하면 다음과 같은 현상이 벌어집니다.

    class ClassV:  # test는 ClassV 클래스의 정의시점에 함께 메모리에 할당됩니다.
    	test = ''
     
    ob = ClassV()  # ob 객체가 생성되기 전에 이미 test는 메모리에 적재된 상태입니다.

    test처럼 클래스와 같은 시간/장소에 정의되는 데이터 속성을 '클래스 속성'이라 하고 인스턴스와 같은 시간/장소에 정의되는 데이터 속성은 '인스턴스 속성'이라 합니다.

    두 속성의 차이가 별거 없어 보이지만 사용자가 예상치 않은 결과를 뱉을 수 있습니다.

    # -*- coding: utf-8 -*-
    class ClassV:
        test = []
        def add(self, test):
            self.test.append(test)
        def print_test(self):
            print(self.test)
    if __name__ == '__main__':
        a = ClassV()
        a.add('a')
        a.print_test()  # ['a'] 출력을 기대
        b = ClassV()
        b.add('b')
        b.print_test()  # ['b'] 출력을 기대
     
    # 결과
    # ['a']
    # ['a', 'b']

    클래스 속성으로 정의된 test 변수를 ClassV의 모든 인스턴스가 공유하게 되어 생긴 문제입니다. 이러한 문제는 인스턴스 속성으로 해결할 수 있습니다.

    정적 메소드와 클래스 메소드

    인스턴스 메소드는 인스턴스 (객체)에 속한 메소드를 말합니다. 여기서 메소드는 클래스에 정의하는데 인스턴스에 속하다는 것에 의문이 들 수 있습니다. 인스턴스 메소드가 "인스턴스에 속한다"라는 표현은 "인스턴스를 통해 호출가능하다"라는 뜻입니다. 인스턴스에 속한 것과 같이 정적 메소드와 클래스 메소드가 클래스에 속한(클래스를 통해 호출 가능한) 메소드입니다.

    정적 메소드 (static method)

    # -*- coding: utf-8 -*-
    class ClassV:
        test = []
        def add(self, test):
            self.test.append(test)
        def print_test(self):
            print(self.test)
        @staticmethod  # 데코레이터 수식
        def plus(a, b):  # self 매개변수 필요 없음
            return a + b
    
    if __name__ == '__main__':
        a = ClassV()
        a.plus(1, 3)  # 정적 메소드는 대개 이렇게 인스턴스를 만들어 호출하지 않습니다.
        a = ClassV.plus(5, 7)  # 정적 메소드는 클래스를 통해 호출하는 것이 보통입니다.
    

    정적 메소드는 self 매개변수를 전달받을 방법이 없어서 객체/인스턴스의 변수에 접근할 수 없습니다. 따라서 정적 메소드는 객체의 데이터 속성과는 관계가 없는 코드로 구현되는 것이 일반적입니다.

    클래스 메소드 (class method)

    # -*- coding: utf-8 -*-
    class ClassV:
        @classmethod  # 클래스 메소드를 정의하기 위해 데코레이터 추가
        def print_test(cls):  # 메소드의 매개변수를 하나 이상 정의
            print(cls)
    ClassV.print_test()  # 클래스를 통한 클래스 메소드 호출
    obj = ClassV()
    obj.print_test()  # 인스턴스를 통한 인스턴스 메소드 호출

    인스턴스 메소드에 self가 필수 매개변수라면 클래스 메소드는 cls가 필수입니다. 위 코드에서 print_test()를 호출할 때마다 ClassV 클래스를 암묵적인 매개변수로 전달했고, print_test()는 매개변수로 받아들인 이 클래스의 정보를 출력하는 예제입니다.

    다음 예제는 클래스의 객체가 얼마나 생성되었는지를 세는 예제입니다.

    # -*- coding: utf-8 -*-
    class InstanceCounter:
        count = 0
        def __init__(self): # 인스턴스가 만들어질 때마다 해당 메소드가 실행되어 인스턴스의 수를 세기에는 가장 적합
            InstanceCounter.count += 1 # 여기서 self로 하면 인스턴스 속성이 되기 때문에 print에는 0으로만 출력된다. 한마디로 클래스명이 붙어 있어 클래스 속성 변수인셈
        @classmethod
        def print_instance_count(cls): # InstanceCounter의 클래스 속성인 count 변수를 출력합니다.
            print(cls.count)
    a = InstanceCounter()
    InstanceCounter.print_instance_count()
    b = InstanceCounter()
    InstanceCounter.print_instance_count()
    c = InstanceCounter()
    c.print_instance_count()
     
    # 결과
    # 1
    # 2
    # 3


    댓글