여러분도 아마 파이썬 코드를 매일 쓰지만, 속에 숨겨진 멋진 기능들을 그냥 지나쳤을지도 몰라요. 오늘은 그중에서도 정말 알아두면 쓸모 있는, 그런데 의외로 많은 사람들이 잘 모르는 기능인 **프로퍼티(Property)**와 **디스크립터(Descriptor)**를 함께 살펴보려고 해요. 이 두 가지는 코드를 더 깔끔하고 효율적으로 만들어주는데요, 여러분도 읽다 보면 "이게 이렇게 편한 거였어?" 하고 놀랄 거예요.
Getter(Getter)와 Setter(Setter): 아, 이걸 또 해야 해?
여러분 혹시 attribute 값을 가져오거나 수정하려고 매번 method를 일일이 써야 했던 적이 있나요? object-oriented programming을 배우다 보면 게터와 세터가 필수처럼 보일 때가 있어요. 뭔지 모르겠다면 걱정하지 마세요. 예제를 하나 보면서 간단히 설명할게요.
class Product:
def __init__(self, price, quantity):
self._price = price # 내부 속성이라고 표시하는 관례
self._quantity = quantity
def get_price(self):
return self._price
def set_price(self, value):
if value < 0:
raise ValueError("가격은 음수가 될 수 없습니다.")
self._price = value
여기서 get_price()로 가격을 가져오고, set_price()로 가격을 설정하죠. 그런데 문제는 이 메서드를 매번 호출해야 한다는 거예요.
예를 들어 가격을 출력하려면 print(product.get_price())처럼 적어야 하고, 값을 변경할 때도 product.set_price(15)라고 써야 하죠. 귀찮고 코드도 길어져요.
"나 여기 있어요!" 파이썬의 구세주, @property
파이썬은 게터와 세터의 번거로움을 해결하기 위해 @property Decorator를 제공해요. 이걸 쓰면 속성에 그냥 자연스럽게 접근할 수 있답니다.
class Product:
def __init__(self, price, quantity):
self._price = price
self._quantity = quantity
@property
def price(self):
return self._price
@price.setter
def price(self, value):
if value < 0:
raise ValueError("가격은 음수가 될 수 없습니다.")
self._price = value
와우, 이제 어떻게 바뀌었는지 보세요:
p = Product(10, 5)
print(p.price) # 간단하게 값을 가져오기!
p.price = 15 # 깔끔하게 값 설정하기!
엄청 간단해졌죠? 더 이상 get_price()나 set_price()를 호출할 필요가 없어요. 그냥 p.price라고 하면 알아서 값을 가져오고 설정합니다. 너무 편해요!
프로퍼티의 숨은 기능들
프로퍼티에는 기본적인 값 가져오기와 설정하기 말고도 알아두면 유용한 고급 기능들이 있어요. 예를 들어볼까요?
읽기 전용 속성 만들기
가격을 바꿀 수 없게 만들고 싶다면 세터 메서드를 그냥 안 만들어도 돼요.
class Product:
def __init__(self, cost):
self._cost = cost
@property
def cost(self):
return self._cost
p = Product(10)
print(p.cost) # 10 출력
p.cost = 20 # AttributeError 발생: 변경할 수 없습니다.
이렇게 하면 외부에서 값을 변경하려고 할 때 오류가 나요. 안전성이 보장되는 거죠.
계산 결과를 캐싱하는 @cached_property
혹시 반복 계산이 무거운 작업일 때가 있나요? 그럴 땐 파이썬의 @cached_property를 사용해서 한 번 계산한 결과를 저장할 수 있어요.
from functools import cached_property
class Product:
def __init__(self, values):
self.values = values
@cached_property
def average(self):
print("평균 계산 중...")
return sum(self.values) / len(self.values)
p = Product([10, 20, 30])
print(p.average) # 처음 호출 시 계산
print(p.average) # 두 번째 호출 시 캐시된 값 반환
첫 번째 호출 때는 계산하지만, 두 번째 호출부터는 캐시된 값을 바로 반환하니까 속도도 빨라지고 자원도 절약되죠.
디스크립터: 숨은 제어자
이제 프로퍼티를 알았으니, 한 단계 더 나아가 디스크립터를 알아볼까요? 디스크립터는 속성의 값을 가져오거나 설정할 때 더 강력한 제어를 가능하게 해주는 기능이에요.
간단한 디스크립터 예제
디스크립터를 사용해 양수 값만 허용하는 속성을 만들어볼게요:
class PositiveNumber:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
return instance.__dict__.get(self.name, 0)
def __set__(self, instance, value):
if value < 0:
raise ValueError(f"{self.name}는 양수여야 합니다.")
instance.__dict__[self.name] = value
class Product:
price = PositiveNumber("price")
quantity = PositiveNumber("quantity")
def __init__(self, price, quantity):
self.price = price
self.quantity = quantity
p = Product(10, 5)
print(p.price) # 10 출력
p.price = -5 # ValueError 발생
디스크립터가 속성 값을 검사해서 양수만 허용하도록 해줘요. 실수로 잘못된 값을 넣으려고 해도 바로 오류가 나니까 걱정 없죠.
디스크립터의 진짜 매력: 실무에서의 활용
여러분이 Django(Django) 같은 프레임워크를 사용해봤다면 디스크립터를 본 적이 있을지도 몰라요. 장고에서 데이터베이스 필드를 정의할 때 이 디스크립터가 내부적으로 사용돼요. 예를 들어, 문자 필드에 문자열만 들어가도록 검사하거나 최대 길이를 초과하지 않도록 하는 것도 디스크립터 덕분이에요.
class CharField:
def __init__(self, name, max_length):
self.name = name
self.max_length = max_length
def __get__(self, instance, owner):
return instance.__dict__.get(self.name, "")
def __set__(self, instance, value):
if not isinstance(value, str):
raise ValueError("문자열이어야 합니다.")
if len(value) > self.max_length:
raise ValueError(f"최대 길이 {self.max_length}을 초과했습니다.")
instance.__dict__[self.name] = value
class Product:
name = CharField("name", max_length=10)
def __init__(self, name):
self.name = name
p = Product("커피 머그")
print(p.name) # 정상 출력
p.name = "너무 길어서 오류" # ValueError 발생
이렇게 디스크립터를 활용하면 데이터 integrity을 보장할 수 있어요.
결론: 배운 걸 어떻게 써볼까?
이제 여러분은 파이썬의 프로퍼티와 디스크립터가 얼마나 강력한 도구인지 알게 됐어요. 게터와 세터의 번거로움에서 벗어나고, 데이터 무결성을 자동으로 검사하면서도 더 깔끔하고 가독성 높은 코드를 작성할 수 있답니다.
이런 기능들을 알아두면 파이썬으로 더 효율적이고 안전한 프로그램을 작성할 수 있어요. 다음에 장고나 Flask에서 이런 구조를 볼 때 "아, 이게 바로 디스크립터구나!" 하고 감 잡을 수 있겠죠? 그러니 계속해서 새로운 기능을 탐구하고, 실전에서 써보세요. 프로그래밍은 탐험하는 재미가 있잖아요!
'SW > Python' 카테고리의 다른 글
파이썬 if __name__ == "__main__" 이해하기: 초보자를 위한 완벽 가이드 (0) | 2025.03.29 |
---|---|
Python : __init__.py 이해하기: 패키지 관리 필수 팁 (0) | 2025.03.25 |
파이썬의 진짜 매력: 던더 메소드 완벽 가이드 (0) | 2025.02.13 |
파이썬으로 돈 버는 법: 초보자를 위한 상세 가이드 및 실천 가능한 전략 (0) | 2025.02.07 |
파이썬을 이용한 이메일 구독 취소 자동화: 단계별 가이드 (0) | 2024.12.15 |