-
Python getter setter propertyPython 2022. 9. 28. 16:19
@property 데코레이터에 대해 알아보자
그전에 선행으로 getter와 setter의 개념부터 알아보자
class User: def __init__(self, name, age): self.name = name self.age = age first_user = User(name="루키", age=12) print(first_user.name) # 루키 print(first_user.age) # 12 first_user.age = first_user.age + 16 print(first_user.age) # 28이런 간단한 구조의 클래스가 있을 때 파이썬에서는 클래스의 인스턴스를 생성 후 필드 값을 읽거나 쓰는 것에 제약이 없다.
객체지향을 처음 공부하며 느낀 점 중 하나이다.
캡슐화로 외부에서 접근을 막기 위해 정보 은닉으로 private로 설정한다고 했는데 파이썬 클래스에는 모두 공개되어 있는데 숨길 방법이 없나 라는 생각이 들었다.
그런 부분에서 찾은 게 getter와 setter이다.
클래스 인스턴스 내부 데이터를 보호하기 위해서 접근용 메서드를 작성하는 것이며 객체 지향 프로그래밍에서 흔히 볼 수 있는 패턴이다.
예시에 getter setter를 적용시켜보자
class User: def __init__(self, name, age): self.name = name self.set_age(age) def get_age(self): return self._age def set_age(self, age): if age < 0: raise ValueError("age value must be positive integer") self._age = age first_user = User(name="루키", age=12) print(first_user.get_age()) # 12 first_user.set_age(age=-10) # ValueError: age value must be positive integer여기서 앞에 _ 하나가 붙는 이유는 어떤 제약이 걸린 것이 아니라 파이썬의 약속이다 _로 시작하는 변수는 외부에서 접근하지 않겠다 즉 private라는 뜻이다.
그렇다면 처음에 설명한 @property는 무엇일까?
이제 클래스의 인스턴스에 있는 나이를 읽거나 쓰려면 getter, setter 메서드를 사용해야 한다.
하지만 기존의 필드명으로 바로 사용할 때보다는 코드가 깔끔하지 못하다.
@property는 메서드를 마치 필드명처럼 사용할 수 있게 해 준다.
class User: def __init__(self, name, age): self.name = name self._age = age @property def age(self): return self._age @age.setter def age(self, age): if age < 0: raise ValueError("age value must be positive integer") self._age = age first_user = User(name="루키", age=12) print(first_user.age) # 12 first_user.age = 10 print(first_user.age) # 10 first_user.age = -1 # ValueError: age value must be positive integer이런 결과로 출력이 될 것이다.
Django model에서도 사용하게 된다.
위의 클래스가 django 모델 클래스라고 가정해보자
from django.db import models class User(models.Model): name = models.CharField( verbose_name="이름", help_text="유저의 이름입니다.", max_length=20, ) age = models.PositiveIntegerField( verbose_name="나이", help_text="유저의 나이입니다.", default=0, ) @property def information(self): return f"{self.name} {self.age}세" user = User.objects.get(name="루키") user.information위와 같이 메서드를 필드명처럼 사용 가능하게 함을 이용하여 사용하고 있다
나는 typing protocol에서 자주 활용하고 있다.
'Python' 카테고리의 다른 글
Python AES256 암호화, 복호화 (0) 2022.12.22 파이썬 오버로딩과 오버라이딩 (2) 2022.11.10 [lambda x: i * x for i in range(4)] (1) 2022.11.07 Python 패키징의 역사 (0) 2022.10.12 Python Celery (0) 2022.10.06