학습내용

파이썬 접근제어

사진 출처 : https://umar-yusuf.blogspot.com/2016/05/an-introduction-to-object-oriented-programming-in-python6.html?m=1

클래스 생성자에 있는 private변수에 접근하기위해서는 _클래스이름__private변수를 활용한다.

priviate 매소드에 접근하기 위해서는 _클래스이름__매소드 를 활용한다.

EX)

  • _single_leading_underscore :

    모듈로써 저장되어 있을때, import하여 사용은 불가능하지만 직접 접근은 허용됨.

    def __init__(self, price):
        self._price = price
    
    def _double_price(self): # private 메서드
        return self._price * self._hidden_factor
    
    def get_double_price(self):
        return self._double_price()
  • __double_leading_underscores :

    직접 가져다가 못씀. ClassName이라는 클래스에서 __method라는 메소드를 선언했다면 이는 __ClassName__method로 맹글링된다. 따라서 접근하기 위해서는 __ClassName__method 로 접근해야함. 또는 클래스안에 새로운 메서드 이름으로 변형시켜 불러오기 가능.

같은 매서드 명을 가지더라도, 클래스 명이 다르면 private은 상속 받을 시에 오버라이딩이 일어나지않는다.

class A:
    def _single_method(self):
        pass

    def __double_method(self): # 맹글링을 위한 메서드
        pass

class B(A):
    def __double_method(self): # 맹글링을 위한 메서드
        pass

print(dir(A())) # ['_A__double_method', ..., '_single_method']
print(dir(B())) # ['_A__double_method', '_B__double_method', ..., '_single_method']

# 서로 같은 이름의 메서드를 가지지만 오버라이드가 되지 않는다.
  • getter, setter

    1. 파이썬 내장함수 property()를 사용

      # case 1 - _get_name에서 property(_get_name, _set_name)
      
      class Color:
           def __init__(self, rgb_value, name):
               self.rgb_value = rgb_value
               self._name = name
           def _set_name(self, name):
               if not name:
                   raise Exception("Invalid Name")
               self._name = name
      
           def _get_name(self):
               return self._name
           name = property(_get_name, _set_name)    # 내장함수 property 활용
           
      c = Color("#0000ff", "bright red")
      print(c.name)   # property를 통해 변수처럼 getter가 가능하다.
      
      c.name = "red"   # property를 통해 변수처럼 setter가 가능하다.
      print(c.name)
    2. @property 활용(데코레이터)

      # case 2 - @property 활용
      # 기존의 메소드에 대해서 새로운 기능을 제공할 수 있다.
      
      class Color:
           def __init__(self, rgb_value, name):
               self.rgb_value = rgb_value
               self._name = name
      
           @property                # getter, 속성을 불러올 수 있음
           def _get_name(self):
               return self._name
           
           @_get_name.setter		  # setter, 속성값을 지정해줄 수 있음
           def _get_name(self, name):
               self._name = name
              
      c = Color("#0000ff", "bright red")
      
      c._get_name #"bright red"
      c._name #"bright red"
      
      c._get_name = 'red' #메소드를 통해 바꿔주기, getter setter에 의해 변수처럼 사용가능
      
      c._get_name #"red"
      c._name #"red"
      
      c._name = "blue" #속성을 통해 바꿔주기
      
      c._get_name #"blue"
      c._name #"blue"

Super

  • super 사용 이유
  1. 클래스가 기존 메서드를 확장하되, 원래 구현을 재정의(오버라이딩)에 포함하고 싶을 수 있다. 이를 위해 super()를 사용

  2. 파이썬3에서는 super를 인수 없이 호출하면 __class__와 self를 인수로 넘겨서 호출한 것으로 처리

    super의 인자는 지정안해주면 현재 클래스로 자동 설정하여 자신의 바로 위 상위 클래스들에게 상속받음

    첫번째 인자는 클래스, 두번째는 인스턴스가 들어감

    아래 예시에서 확인 가능.

  3. 다중상속문제 해결 가능

    상위 클래스들이 같은 클래스를 통해 상속 받고 있는 경우, 최상위 클래스의 생성자가 중복되어 실행되는 경우가 있음.

    이를 super를 통해 해결가능

A-B-D
 \C/

class A:
   def __init__(self):

      print("Class A __init__()")

class B(A):

   def __init__(self):

      print("Class B __init__()")

      A.__init__(self)

class C(A):

   def __init__(self):

      print("Class C __init__()")

      A.__init__(self)

class D(B, C):

   def __init__(self):

      print("Class D __init__()")

      B.__init__(self)

      C.__init__(self)
      
d = D()

# 출처: https://bluese05.tistory.com/5 [ㅍㅍㅋㄷ]
class A:

   def __init__(self):

      print("Class A __init__()")

      super(A, self).__init__()


class B(A):

   def __init__(self):

      print("Class B __init__()")

      super(B, self).__init__()


class C(A):

   def __init__(self):

      print("Class C __init__()")

      super(C, self).__init__()


class D(B, C):

   def __init__(self):

      print("Class D __init__()")

      super(D, self).__init__()


d = D()


# 출처: https://bluese05.tistory.com/5 [ㅍㅍㅋㄷ]

변수

실행순서

로컬 범위가 항상 먼저 검색 -> Enclosing을 통해 로컬의 범위를 탐색 -> Global

특별 메소드

magic method라고도 불림

  • __init__ : 생성자가 생성될 때 객체를 초기화

  • __call__ : 객체가 호출되면 실행

  • __getattribute__ : 객체에 없는 속성을 호출하면 실행

정적 메소드

  • class method 와 static method로 나눠짐
  • 공통점 : 클래스에 대한 별도의 인스턴스를 생성할 필요없이 메소드를 바로 사용할 수 있다. 즉 self가 class에 없다.

  • 차이점 :

    • classmethod는 cls가 있는데 이것은 '클래스'를 가리킨다. 이것으로 클래스의 어떤 속성에도 접근할 수 있다.
    • static method는 별도의 정적변수(클래스이름)를 생성하여 접근해야 하므로, 코드의 가독성이 좋지 않다.
    #staticmethod
    class hello:
        num = 10
    
        @staticmethod
        def calc(x):
            return x + 10 + hello.num
    
    print(hello.calc(10))
    #결과
    30
    
    #classmethod
    class hello:
        num = 10
    
        @classmethod
        def calc(cls, x):
            return x + 10 + cls.num
    
    print(hello.calc(10))
    #결과
    30
    
    #출처 : https://wikidocs.net/21054

Reference

https://okky.kr/article/558251

https://wikidocs.net/21054

https://bluese05.tistory.com/5 [ㅍㅍㅋㄷ]

0개의 댓글