클래스 생성자에 있는 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
파이썬 내장함수 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)
@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()를 사용
파이썬3에서는 super를 인수 없이 호출하면 __class__와 self를 인수로 넘겨서 호출한 것으로 처리
super의 인자는 지정안해주면 현재 클래스로 자동 설정하여 자신의 바로 위 상위 클래스들에게 상속받음
첫번째 인자는 클래스, 두번째는 인스턴스가 들어감
아래 예시에서 확인 가능.
다중상속문제 해결 가능
상위 클래스들이 같은 클래스를 통해 상속 받고 있는 경우, 최상위 클래스의 생성자가 중복되어 실행되는 경우가 있음.
이를 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__ : 객체에 없는 속성을 호출하면 실행
공통점 : 클래스에 대한 별도의 인스턴스를 생성할 필요없이 메소드를 바로 사용할 수 있다. 즉 self가 class에 없다.
차이점 :
#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