getter, setter : 객체의 내부 변수에 접근할 때 특정 메소드를 거쳐서 접근할 수 있도록 하는 방법
이름과 패스워드를 갖는 유저 객체를 생성해보자.
class User: def __init__(self, name, pw): self.name = name self.pw = pw user = User('peter', 'abcd123') # 유저 객체를 생성
이름이 peter이며 패스워드를 abcd123로 사용하는 유저 객체 user를 생성했다.
유저의 패스워드를 출력 시도한다면?
print(user.pw) # 실행 결과 abcd123
패스워드는 쉽게 공개되지 않아야 하는데 그대로 노출되었다.
문제점을 해결하기 위해 패스워드 변수에 대해 제한 사항을 설정한다.
먼저 패스워드를 출력하는 경우 앞 2글자만 보여지고 나머지는 별표로 처리한다.
그리고 패스워드 변경할 경우 현재 패스워드를 입력해야 하며 틀릴 경우 'wrong password'를 출력한다.
getter, setter 설정방법은 decorator를 이용하는 방법과 property 함수를 이용하는 방법이 있다.
두 방식 코드는 기능상 차이가 없다.
1. decorator 이용 방법
# decorator 이용 방법 class User: def __init__(self, name, pw): self.name = name self.hidden_pw = pw @property def pw(self): print('getter') return self.hidden_pw[:2] + '*' * len(self.hidden_pw[2:]) @pw.setter def pw(self, new_pw): print('setter') input_pw = input('insert password : ') if input_pw == self.hidden_pw: self.hidden_pw = new_pw print('password changed') else: print('wrong password')
해당 형태에서 패스워드에 접근하여 값을 얻는 메소드와 값을 변경하는 메소드의 이름은 일치시켜야 하며
decorator는 @property, @메소드이름.setter 형태로 사용한다.
2. property 함수 이용 방법
# property 함수 이용 방법 class User: def __init__(self, name, pw): self.name = name self.hidden_pw = pw def getter(self): print('getter') return self.hidden_pw[:2] + '*' * len(self.hidden_pw[2:]) def setter(self, new_pw): print('setter') input_pw = input('insert password : ') if input_pw == self.hidden_pw: self.hidden_pw = new_pw print('password changed') else: print('wrong password') pw = property(getter, setter) # property 함수 사용
위와 같이 2가지 방법을 통해 코드를 바꿔 제한사항을 설정한 후, 전과 같이 패스워드에 접근해 보자.
user = User('peter', 'abcd123') user.pw = 'qwer456' # 값을 저장할 때는 setter 함수를 거침 # 실행 결과 setter insert password : abcd123 password changed
유저 객체를 생성하고 패스워드를 qwer456으로 변경하는 과정에서 현재 패스워드 abcd123를 입력해야 변경이 가능하게 되었다.
print(user.pw) # 실행 결과 getter qw*****
변경된 패스워드 qwer456 중 qw만 마스킹되지 않고 출력된 결과를 볼 수 있다.
하지만 두 방식 모두 문제점이 있다.
user.hidden_pw = 'kkkk99' # 문제점 : 직접 접근해서 변경 print(person.hidden_pw) # 문제점 : 직접 접근해서 확인 # 실행 결과 kkkk99
User 객체의 hidden_pw 변수에 직접 접근하여 패스워드를 변경하고 확인할 수 있었다.
name mangling
이를 해결하기 위해 맹글링을 사용한다.
변수를 non public 하게 만들어 주어 숨기는 방식(은닉)하는 방식이다.
변수 앞에 __(double underscore)를 붙여주는 형태로 사용한다.
위에서 소개한 property 함수를 이용한 getter, setter에 name mangling을 적용해 보자.
# property 함수 이용 + name mangling 이용 방법 # hidden_pw 변수 앞에 __ 추가 class User: def __init__(self, name, pw): self.name = name self.__hidden_pw = pw def getter(self): print('getter') return self.__hidden_pw[:2] + '*' * len(self.__hidden_pw[2:]) def setter(self, new_pw): print('setter') input_pw = input('insert password : ') if input_pw == self.__hidden_pw: self.__hidden_pw = new_pw print('password changed') else: print('wrong password') pw = property(getter, setter)
name mangling까지 적용한 클래스를 활용해서 객체를 만들고 패스워드에 접근해 보자.
user = User('jonadan', 'erty677') print(user.pw) # 실행 결과 getter er*****
패스워드 erty677인 현 상태
-> __hidden_pw 변수에 직접 uqwe88로 변경 시도 후 확인
person.__hidden_pw = 'uqwe88' # 에러는 나지 않음 print(user.pw) # 실행 결과 - 패스워드가 변경되지 않았다 getter er*****
다시 setter를 통해 변경 시도
user.pw = 'uqwe88' # 실행 결과 setter insert password : erty677 password changed
print(user.pw) # 실행 결과 getter uq****
__hidden_pw 변수 직접 접근은 불가하지만 setter를 통해서는 잘 변경된 것을 확인할 수 있다.
그러나...
print(user._User__hidden_pw) # 실행 결과 uqwe88
사실 내부적으로 _클래스명이 name mangling 된 변수 앞에 붙는다.
클래스를 엄격하게 통제하지 않는 파이썬의 특성상 맹글링을 사용해도 직접 접근을 완전히 막을 수는 없다.
'AI SCHOOL > TIL' 카테고리의 다른 글
[DAY 12] API, 로봇 배제 표준, FinanceDataReader 등 (0) | 2023.01.10 |
---|---|
[DAY 11] pandas 기초 - DataFrame, Series, Indexing 등 (2) | 2023.01.10 |
[DAY 9] 클래스, 객체, 메소드 (2) | 2023.01.05 |
[DAY 8] parameter와 argument, lambda, list comprehension (0) | 2023.01.05 |
[DAY 7] 데이터 핸들링 스킬, 파이썬 연산자와 함수 (0) | 2023.01.05 |
댓글