ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 파이썬 인스턴스 메서드 / 정적 메서드 / 클래스 메서드
    Engineering WIKI/Python 2022. 4. 12. 13:49

    0. 파이썬의 메서드 종류

    • 메서드는 클래스의 행위를 표현하는 것으로 클래스 내의 함수로 볼 수 있다.
    • 파이썬에서 메서드는 크게 3가지로 볼 수 있다.
      • 인스턴스 메서드(instance method) : 아래 1번에서 자세히 설명
      • 정적 메서드(static method) : 아래 2번에서 자세히 설명
      • 클래스 메서드(class method) : 아래 3번에서 자세히 설명
    class CustomClass:
        
          # instance method
          def add_instance_method(self, a,b):
              return a + b
        
          # classmethod
          @classmethod
          def add_class_method(cls, a, b):
              return a + b
        
          # staticmethod
          @staticmethod
          def add_static_method(a, b):
              return a + b
    
    class SelfTest:
    
        @staticmethod
        def function1(a): 
            print(a)
            print('function1 called')
        
        @staticmethod
        def function2():
            print('function2 called')
        
        @classmethod
        def function3(cls): 
            print('function3 called')
        
        def function4(self):
            print('function4 called')
    	
        def function5():
            print('function5 called')
    
    self_test = SelfTest() 
    
    test = self_test.function1(2) # a, function1 called
    
    self_test.function2() #functio2 called
    SelfTest.function2() #function2 called
    
    self_test.function3() #function3 called
    
    self_test.function4() #function4 called
    
    SelfTest.functiont5() # function5 called
    
    self_test.function5() # Error 
    
    
    • 위와 같이 function5 메소드 같은겨우 @staticmethod를 붙이지 않는경우 인스턴화 후 접근 불가하므로 SelfTest.function5() 와 같이 클래스명.메소드명으로 접근해야 한다

    1. 인스턴스 메서드(instance method)

    • 가장 흔히 쓰이는 것으로, 인스턴스 변수에 엑세스할 수 있도록 첫 번째 인자에 항상 객체 자신을 의미하는 self파라미터를 갖는다.(self이외에도 여러개의 파라미터를 가질 수 있다.)
    • 해당 메서드를 호출한 객체에만 영향을 미친다.
    • 객체 속성에 접근이 가능하다.
    • 호출 방법
      • 해당 클래스 안에서는 self.메서드명
      • 클래스 밖에서는 객체.메서드명
    • 예시 코드
      • 아래 코드에서 print_info(), test_func() 가 인스턴스 메서드에 해당한다.
      • #1 :메서드 안에서 메서드를 호출 할 때는 self.메서드() 형식으로 호출한다.
      • #2, #3 클래스 밖에서는 객체.메서드명
    class Test:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def print_info(self):
            print(self.name, ',', self.age)
    
        def test_func(self):
            self.print_info #1
    
    test1 = Test('hong', 22)
    test1.print_info() #2  결과값 : hong , 22
    test1.test_func() #3 결과값 : hong , 22
    

    2. 정적 메서드(static method)

    • 객체와 독립적이지만, 로직상 클래스 내에 포함되는 메서드이다.
    • self파라미터를 가지고 있지 않다. 따라서, 인스턴스 변수에 액세스가 불가능하다.
      • 그러나, 정적 메서드 내부에서 클래스 변수(속성) 에는 클래스명.클래스속성명으로 엑세스가 가능하다.
      • 파이썬에서는 다른언어와는 다르게 정적메소드임에도 불구하고 인스턴스에서도 접근이 가능합니다. 이 차이에 유의해야합니다.
    • 정적 메서드는 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수 함수(pure function)을 만들 때 사용한다.
      • 순수 함수란 부수 효과(side effect)가 없고, 입력 값이 같으면 언제나 같은 출력값을 반환한다.
      • 즉, 인스턴스 상태를 변화시키지 않는 메서드를 만들 때 사용한다.
    • @staticmethod라는 데코레이터를 붙여서 해당 메서드가 정적 메서드임을 표시한다.
    • 호출 방법 ; 클래스명.정적메서드명 또는 객체명.정적메서드명 둘 다 호출 가능하지만, 전자를 주로 사용한다.
    • 예시 코드
    class Calc:
    
        count = 10 # 클래스 변수(클래스 속성)
    
        @staticmethod
        def add(a):
            print(a + Calc.count) # 클래스 속성에는 엑세스가 가능하다.
    
        @staticmethod
        def mul(a):
            print(a * Calc.count)
    
    Calc.add(15) # 결과값 :25
    Calc.mul(15) # 결과값 : 150
    
    calc_result = Calc()
    calc_result.mul(10) # 결과값 : 100
    
    • 참고 - 파이썬 자료형의 인스턴스 메서드와 정적 메서드
      • 파이썬의 자료형도 인스턴스 메서드, 정적 메서드, 클래스 메서드로 나뉘어져 있다.
      • 아래 예시와 같이, 인스턴스 내용을 변경할 때는 update와 같이 인스턴스 메서드로 작성하면 되고,
      • 인스턴스 내용과는 상관없이 결과만 구하면 될 때는 #1과 같이 정적 메서드로 작성한다.
    a = {1, 2, 3, 4}
    a.update({5}) # 인스턴스 메서드
    print(a) # 결과값 {1, 2, 3, 4, 5}
    
    print(set.union({1, 2, 3, 4}, {5})) #1 정적 메서드, 결과값 {1, 2, 3, 4, 5}
    

    3. 클래스 메서드 (class method)

    • 인스턴스 없이 호출이 가능하다는 점에서 정적 메서드와 비슷하지만 약간의 차이점이 있다.
    • self파라미터 대신 cls라는 클래스를 의미하는 파라미터를 갖는다.
    • 해당 클래스로 생성된 객체로 부터 호출 되는 것이 아니라, 클래스 자체에서 직접 호출된다.
    • 객체의 속성/메서드에는 엑세스가 불가능하다.
      • 그러나, cls.클래스속성명으로 클래스 속성에는 접근 가능하다.
    • cls를 사용하면 클레스 메서드 내부에서 현재 클래스의 인스턴스를 만들 수도 있다. (cls() = 현재클래스명() 를 의미. 아래 예시 코드로 확인)
    • @classmethod라는 데코레이터를 붙여 해당 메서드가 클래스 메서드임을 표시한다.
    • 호출 방법 ; 클래스명.클래스메서드명 또는 객체명.클래스메서드명 둘다 호출 가능하다.
    • 예시 코드
    class Person:
        count = 0 # 클래스 속성
    
        def __init__(self):
            Person.count += 1
    
        @classmethod
        def print_count(cls):
            print('{0}명 생성되었습니다.'.format(cls.count)) # 클래스 속성에는 엑세스가 가능하다.
    
        @classmethod
        def create(cls):
            p = cls() # 메서드 내부에서 cls()로 현재 클래스의 인스턴스를 만들 수도 있다. 즉, cls() = Person()을 의미한다.
            return p
    
    ryan = Person() # 1명
    apeach = Person() # 2명
    Person.create() # 3명
    
    Person.print_count() # 결과값 : 3명 생성되었습니다.
    
    print(Person.create()) # 결과값 : <__main__.Person object at 0x000001BA0AE143D0> Person클래스로 부터 생성된 인스턴스임을 확인할 수 있다.
    

    4. 정적 메서드 vs 클래스 메서드

    • classmethod와 static메소드의 차이는 상속에서 두드러지게 차이가 납니다.
    class Language:
          default_language = "English"
        
          def __init__(self):
              self.show = '나의 언어는' + self.default_language
        
          @classmethod
          def class_my_language(cls):
              return cls()
        
          @staticmethod
          def static_my_language():
              return Language()
        
          def print_language(self):
              print(self.show)
        
        
      class KoreanLanguage(Language):
          default_language = "한국어" 
    
    • staticmethod에서는 부모클래스의 클래스속성 값을 가져오지만, classmethod에서는 cls인자를 활용하여 cls의 클래스속성을 가져오는 것을 알 수 있습니다.
    from language import *
    
    a = KoreanLanguage.static_my_language()
    b = KoreanLanguage.class_my_language()
    
    a.print_language()
      #나의 언어는English
    b.print_language()
      #나의 언어는한국어
    
    • 아래 두 예시 코드의 결과를 비교해보자.
    • 예시 코드 : 클래스 메서드로 작성
    class Figure:
        @classmethod
        def set_name(cls, name):
            cls.name = name
    
    # Figure 클래스를 상속받음
    class Circle(Figure):
        pass
    
    Figure.set_name("figure")
    print(Figure.name, Circle.name) # 결과값 : figure figure
    
    Circle.set_name("circle")
    print(Figure.name, Circle.name) # 결과값 : figure circle
    
    • 예시 코드 : 정적 메소드로 작성
    class Figure:
        @staticmethod
        def set_name(name):
            Figure.name = name
    
    # Figure 클래스를 상속받음
    class Circle(Figure):
        pass
    
    Figure.set_name("figure")
    print(Figure.name, Circle.name) # 결과값 : figure figure
    
    Circle.set_name("circle")
    print(Figure.name, Circle.name) # 결과값 : circle circle
    
    • 이때 클래스 메소드는 cls로 현재 자기가 실행된 클래스 속성을 가져오고, 정적 메소드는 부모 클래스(Windows)의 속성을 가져오게 됩니다.
Designed by Tistory.