본문 바로가기
Programming/Python

24. 프라이빗 변수(Private Variable)와 게터 / 세터 (Getter / Setter)

by IT learning 2021. 3. 28.
728x90

오늘은 프라이빗 변수와 게터/세터에 대해 알아보겠다.

 

객체 지향 프로그래밍의 최종 목표는 객체를 효율적으로 만들고 사용하는 것이다.

 

객체를 효율적으로 사용한다는 것은 어떤 말일까?

# 원의 둘레와 넓이를 구하는 객체 지향 프로그램
import math

class Circle:
    def __init__(self, radius):
        self.radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.radius
    def get_area(self):
        return math.pi * (self.radius ** 2)
    
# 원의 둘레와 넓이를 구합니다.
circle = Circle(10)
print("원의 둘레: {:.3f}".format(circle.get_circumference()))
print("원의 넓이: {:.3f}".format(circle.get_area()))

위 코드를 살펴보자.

원의 둘레와 넓이를 구하는 객체 지향 프로그램을 만들어 보았다.

 

class 로 Circle 클래스를 선언하고, 각 기능들을 삽입했다.

위 코드의 실행결과이다.

실행결과도 잘 나온다.

 

근데, Circle 클래스의 radius 속성에 음수를 넣으면 어떻게 될까?

-2 삽입 결과이다.

계산이 잘 된다!...가 아니라.

원의 넓이는 제곱해서 괜찮지만, 둘레는 음수가 나온다.

 

생각해보자. 현실에서는 길이가 음수가 나올 수 있는가? 그럴 수 없다.

따라서 길이를 음수로 넣는 것을 막는 방법이 필요하다.

 

프라이빗 변수

일단 변수를 마음대로 사용하는 것을 막아야 한다.

파이썬은 내부의 변수를 외부에서 사용하는 것을 막고 싶을 때 인스턴스 변수 이름을 __<변수이름> 형태로 선언한다. 언더 바 2개다. 

# 프라이빗 변수
import math

class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.__radius
    def get_area(self):
        return math.pi * (self.__radius ** 2)
    
# 원의 둘레와 넓이를 구합니다.
circle = Circle(10)
print("원의 둘레: {:.3f}".format(circle.get_circumference()))
print("원의 넓이: {:.3f}".format(circle.get_area()))

# __radius에 접근합니다.
print("# __radius에 접근합니다.")
print(circle.__radius)

위 코드를 살펴보자.

radius를 프라이빗 변수로 선언하여 사용하고 있다.

위 코드의 실행결과이다.

둘레와 넓이는 문제가 없으니 출력이 된다.

하지만, 뒤쪽에 radius에 접근하는 코드는 예외가 뜨기 마련이다.

왜냐? radius를 프라이빗 변수로 선언했으니 외부에서 접근할 수 없기 때문이다.

 

게터와 세터

그런데 중간에 원의 둘레를 변경하고 싶다면 어쩔까? 변경도 못하고 시무룩하게 있을 순 없지 않은가..

클래스 외부에서 직접 접근할 수 없기 때문에, 간접적으로 접근할 수 있는 방법이 필요하다.

 

그때 사용하는게 게터와 세터이다.

게터와 세터는 프라이빗 변수의 값을 추출하거나 변경할 목적으로, 간접적으로 속성에 접근 할 수 있도록 해주는 함수이다.

# 게터와 세터
import math

class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.__radius
    def get_area(self):
        return math.pi * (self.__radius ** 2)
    
    # 게터와 세터를 선언합니다.
    def get_radius(self):
        return self.__radius
    def set_radius(self, value):
        self.__radius = value
        

circle = Circle(10)
print("원의 둘레: {:.3f}".format(circle.get_circumference()))
print("원의 넓이: {:.3f}".format(circle.get_area()))
print()

# 간접적으로 __radius에 접근합니다.
print("# __radius에 접근합니다.")
print(circle.get_radius())
print()

# 원의 둘레와 넓이를 구합니다.
circle.set_radius(2)
print("# 반지름을 변경하고 원의 둘레와 넓이를 구합니다.")
print("원의 둘레: {:.3f}".format(circle.get_circumference()))
print("원의 넓이: {:.3f}".format(circle.get_area()))

위 코드를 살펴보자.

Circle 클래스 안에 get_radius 와 set_radius 두개의 함수가 생성되었다.

각 기능은 get에서는 radius의 값을 리턴, set에서는 radius의 값을 value의 매개변수로 변경 이다.

위 코드의 실행결과이다.

초반에 원래 원의 둘레, 넓이를 구하고 radius의 값을 리턴하는 출력을 보았다.

 

그리고 두번째 실행결과에서는 set_radius로 수를 변경하고 출력했다. 결과가 달라졌다.

이렇게 함수를 사용해 값을 변경하면 여러 가지 처리를 추가할 수 있다.

 

이런 방법으로 아까 음수로 입력된 수를 방지하는 코드도 짤 수가 있다.

# 게터 세터로 변수를 안전하게 사용하기
def set_radius(self, value):
	if value <= 0:
    	raise TypeError("길이는 양의 숫자여야 합니다.")
    self.__radius = value

이렇게 짠다면 0 이하의 숫자에 방지를 할 수 있을 것이다.

 

테코레이터를 사용한 게터와 세터

게터와 세터를 함수로 만드는 일이 많아져서 파이썬에서는 게터와 세터를 쉽게 만들고 사용할 수 있게 하는 기능을 제공한다.

# 데코레이터를 사용해 게터와 세터 만들기
import math

class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.__radius
    def get_area(self):
        return math.pi * (self.__radius ** 2)
    @property
    def radius(self):
        return self.__radius
    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise TypeError("길이는 양의 숫자여야 합니다.")
        self.__radius = value
        
print("# 데코레이터를 사용한 Getter와 Setter")
circle = Circle(10)
print("원래 원의 반지름:", circle.radius)
circle.radius = 2
print("변경된 원의 반지름:", circle.radius)
print()

# 강제로 예외를 발생시킵니다.
print("# 강제로 예외를 발생시킵니다.")
circle.radius = -10

위 코드를 살펴보자.

변수 이름과 같은 함수를 정의 하고, 위에 @property와 @<변수 이름>.setter라는 데코레이터를 붙여주면 된다.

위 코드의 실행결과이다.

이렇게 하면 circle.radius를 사용하는 것만으로 자동으로 게터와 세터가 호출되도록  있다.

 

오늘은 프라이빗 변수와 게터/세터를 공부해보았다.

위 개념들은 어느 언어를 가든간에 있는 개념들이니 꼭 숙지하기 바란다.

728x90

'Programming > Python' 카테고리의 다른 글

25. 상속(Inheritance)  (0) 2021.03.28
23. 가비지 컬렉터(Garbage Collector)  (0) 2021.03.28
22. 클래스의 추가적인 구문  (0) 2021.03.27
21. 클래스  (0) 2021.03.26
20. 모듈 만들기  (0) 2021.03.25

댓글

IT_learning's Commit