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 |
댓글