[코딩도장] getter, setter 그리고 프로퍼티(property)


세상엔 모르는거 투성이다. 모르고 넘어가면 후회할거 같아서 남겨본다. 이번 주제는 set, get 그리고 프로퍼티다.


getter, setter 쓰는 이유

init에 있는 변수를 아무렇게 접근해서 고칠수 없게 특정 값만으로 고칠수 있게 쓰는 용도로 이해하자 일단

class안에 변수가 외부에서 바뀌는게 싫다.

파이썬에서 class를 사용하여 객체를 쓰게되면 큰 문제가 class로 선언된 객체의 변수를 밖에서 마음껏 바꿀수 있다는것
아래처럼 c1의 v1에 대한 변수를 변경시키면 subtract메소드의 결과값이 바뀌게 된다.

class Cal(object):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
    def add(self):
        return self.v1+self.v2
    def subtract(self):
        return self.v1-self.v2
c1 = Cal(10, 10)
print(c1.add()) # 20
c1.v1 = 20
print(c1.subtract()) # 10

c2 = Cal(30, 20)
print(c2.add()) # 50
print(c2.subtract()) # 10

변수 앞의 __

위처럼 안되게 할라면 어떻게 해야될까? 아래 코드를 보자.

class Cal(object):
    def __init__(self, v1, v2):
        self.__v1 = v1
        self.__v2 = v2
    def add(self):
        return self.__v1+self.__v2
    def subtract(self):
        return self.__v1-self.__v2
c1 = Cal(10, 10)
print(c1.add()) # 20
c1.v1 = 20
# print(c1.__v1) # error
print(c1.subtract()) # 0

c2 = Cal(30, 20)
print(c2.add()) # 50
print(c2.subtract()) # 10

위 코드처럼 class 내부의 변수를 나타날때 __를 변수앞에 쓰면 내부에서만 변경 시킬수 있고 외부에서는 접근할수 없다.

get, set

그렇다면 임의로 바꾸고 싶을땐 어떻게 할까?
맨앞에 방법말고 접근을 돌려서 할수있는 방법을 만들어보자
이럴때 get, set 함수를 쓴다. get은 변수값을 불러오는 함수, set은 다른값을 변수에 지정할수 있게 하는 함수다.

class Cal(object):
    def __init__(self, v1, v2):
        self.__v1 = v1
        self.__v2 = v2
    def get_v1(self): # v1만 언급했고 v2도 만들어줘야함. 예시니까 그냥 Go
        return self.__v1
    def set_v1(self, v1):
        self.__v1 = v1
    def add(self):
        return self.__v1+self.__v2
    def subtract(self):
        return self.__v1-self.__v2
c1 = Cal(10, 10)
print(c1.add()) # 20
c1.set_v1(20) # set 함수를 통해 변수 변화
print(c1.subtract()) # 10

property와 메서드이름.setter

위의 예제는 c1.set_v1(20) 처럼 함수처럼 쓰는데, property랑 setter를 쓰면 메서드를 속성처럼 사용할 수 있다. 무슨말인지 모르겠다면 아래 코드를 보자

class Cal(object):
    def __init__(self, v1, v2):
        self.__v1 = v1
        self.__v2 = v2
    
    @property
    def get_v1(self):
        return self.__v1

    @get_v1.setter
    def set_v1(self, v1):
        self.__v1 = v1
    
    def add(self):
        return self.__v1+self.__v2
    
    def subtract(self):
        return self.__v1-self.__v2
c1 = Cal(10, 10)
print(c1.add()) # 20
# print(c1.v1) # AttributeError: 'Cal' object has no attribute 'v1'
print(c1.get_v1) # 10
c1.set_v1 = 20
print(c1.subtract()) # 10

위처럼 c1.set_v1 = 20 처럼 값을 할당할수있다.

getter, setter를 사용한 Shop class 구현

class Shop:
    SHOP_TYPE_LIST = ['샌드위치', '패스트푸드']
    def __init__(self, name, shop_type, address):
        self.name = name
        self.__shop_type = shop_type
        self.address = address
        
    def show_info(self):
        return(
            f'상점정보: {self.name}\n'
            f'유형: {self.__shop_type}\n'
            f'주소: {self.address}'
        )
    
    @property
    def shop_type(self):
        return self.__shop_type
 
    @shop_type.setter
    def shop_type(self, new_shop_type):
        if new_shop_type in self.SHOP_TYPE_LIST:
            self.__shop_type = new_shop_type
        else:
            print('{} 중에 하나이어야 합니다.'.format(
            ', '.join(self.SHOP_TYPE_LIST)
            ))

한줄요약

  • property 를 사용하는 이유는 원래 return 하려는 값을 바로 출력해주는 것
  • 특정 함수를 속성처럼 접근(subway.name, subway.address 와 같이 접근)
  • property 는 속성처럼 접근하기 때문에 subway.shop_type() 과 같이 접근할 수는 없음
  • 속성은 subway.name으로 접근을 하지 subway.name() 으로 접근하지는 않는다.
  • @property 의 shop_type 은 속성이며, @shop_type.setter 은 속성이 아니다.(str)

getter 와 setter 를 사용하는 이유

위의 코드를 보면 SHOP_TYPE_LIST 에 정의한 리스트에 대해서만 setter 속성에서 변경 가능하도록 설정한 것처럼 class 자체에서 정의한 list 에 정의한 값에 한정해서 변경할 수 있도록 하는 것이 setter 함수의 이용 방법이다. 일반적으로 성별, 직업 등과 같이 정해진 카테고리 안에서만 변경이 가능하도록 설정



참고1
참고2 중요 참고




© 2018. by statssy

Powered by statssy