2023-01-26 22:18:36

비공개 속성

비공개 속성(private attributes)이란 클래스 외부에서 접근할 수 없는 속성을 의미합니다. 속성 이름 앞에 밑줄을 두 개 붙이면 비공개 속성이 됩니다. 다음 예제 코드에서 SoccerTeam이라는 클래스 안에 self.__win_weight, self.__draw_weight, self.__lose_weight가 비공개 필드입니다. 

 

class SoccerTeam:
    def __init__(self, name, win, draw, lose):
        self.name = name 
        self.win = win
        self.draw = draw
        self.lose = lose
        self.__win_weight = 3
        self.__draw_weight = 1
        self.__lose_weight = 0
        self.win_pts = 0

    def cal_pts(self):
        self.win_pts = self.__win_weight * self.win + self.__draw_weight * self.draw + self.__lose_weight * self.lose


team1 = SoccerTeam('아스날', 16, 2, 1)
team1.cal_pts()
print(team1.win_pts)
print(team1.win, team1.draw, team1.lose)
print(team1.__win_weight)

 

다른 공개 속성과는 달리 클래스 외부에서 접근하고자 하면 에러가 발생합니다. 

 

 

존재하지 않는 속성이라고 에러 메시지를 띄워줍니다. 실제로는 존재하지만 말이죠. 

 

게터, 세터

이러한 비공개 속성의 값을 확인하고 싶거나, 값을 변경하고 싶을 때는 메소드를 활용할 수 있습니다. 값을 얻기 위해 사용되는 메소드를 보통 게터(getter)라고 하고, 값을 변경하기 위해 사용되는 메소드를 세터(setter)라고 합니다. 승리 가중치 변수의 값을 얻고, 수정하는 게터와 세터를 만들어보겠습니다. 

 

class SoccerTeam:
    def __init__(self, name, win, draw, lose):
        self.name = name 
        self.win = win
        self.draw = draw
        self.lose = lose
        self.__win_weight = 3
        self.__draw_weight = 1
        self.__lose_weight = 0
        self.win_pts = 0

    def cal_pts(self):
        self.win_pts = self.__win_weight * self.win + self.__draw_weight * self.draw + self.__lose_weight * self.lose

    def get_win_weight(self):
        return self.__win_weight

    def set_win_weight(self, new_win_weight):
        self.__win_weight = new_win_weight


team1 = SoccerTeam('아스날', 16, 2, 1)
team1.cal_pts()
print(f"승점: {team1.win_pts}")
print(team1.get_win_weight())
team1.set_win_weight(5)
team1.cal_pts()
print(f"승점: {team1.win_pts}")

 

게터와 세터 덕분에 비공개 속성의 값을 얻고, 변경할 수 있게 되었습니다. 새로운 승리 가중치로 인해, 다시 계산한 승점도 변경된 것을 확인하실 수 있습니다. 

 

 

@property

비공개 속성의 값을 얻고 수정하는 간단한 일을 위해 게터, 세터를 위와 같은 방식으로 만드는 것이 조금 번거롭게 느껴지실 수도 있겠습니다. @property 데코레이터를 활용하면 조금 더 간편하게 게터와 세터를 선언할 수 있습니다.

 

class SoccerTeam:
    def __init__(self, name, win, draw, lose):
        self.name = name 
        self.win = win
        self.draw = draw
        self.lose = lose
        self.__win_weight = 3
        self.__draw_weight = 1
        self.__lose_weight = 0
        self.win_pts = 0

    def cal_pts(self):
        self.win_pts = self.__win_weight * self.win + self.__draw_weight * self.draw + self.__lose_weight * self.lose

    # 게터
    @property
    def win_weight(self): 
        return self.__win_weight

    # 세터
    @win_weight.setter
    def win_weight(self, new_win_weight):
        self.__win_weight = new_win_weight


team1 = SoccerTeam('아스날', 16, 2, 1)
team1.cal_pts()
print(f"승점: {team1.win_pts}")
print(team1.win_weight)
team1.win_weight = 5
team1.cal_pts()
print(f"승점: {team1.win_pts}")

 

게터로 사용될 메소드 위에는 @property 데코레이터를 붙여주고, 세터로 사용될 메소드 위에는 @속성명.setter 데코레이터를 붙여줍니다. 이제는 원래 인스턴스 속성 값을 얻고 변경하는 것처럼 사용할 수 있게 되었습니다. 

 

 

 

참고자료

[1] https://www.youtube.com/watch?v=l8PoJ1kJQjA 

[2] 브렛 슬라킨 지음, 오현석 옮김, "파이썬 코딩의 기술", 길벗