property의 핵심은 getter/setter 문법 자체보다, 호출하는 쪽에서 필드처럼 읽히게 유지할 가치가 있는가입니다.
검증이나 계산 로직이 있지만 호출 문법은 속성처럼 남기고 싶을 때 @property가 자연스럽고, 그렇지 않으면 공개 필드가 더 단순할 수 있습니다.
핵심 정리
class User:
def __init__(self, age: int) -> None:
self.age = age
@property
def age(self) -> int:
return self._age
@age.setter
def age(self, value: int) -> None:
if value < 0:
raise ValueError("age must be >= 0")
self._age = value문법
기본형은 getter와 setter 두 가지를 함께 보면 됩니다.
class User:
@property
def age(self) -> int:
return self._age
@age.setter
def age(self, value: int) -> None:
self._age = valueproperty 선택
속성처럼 읽히되 내부 로직을 숨기고 싶으면 @property
처음에는 단순 속성처럼 쓰다가, 나중에 검증이나 계산 로직이 필요해질 수 있습니다.
property는 호출 문법을 바꾸지 않고 내부 구현을 바꿀 수 있게 해 줍니다.
user.age # 메서드 호출이 아니라 속성처럼 읽힘
user.age = 30 # setter를 거쳐 검증 가능이 점 때문에 Python에서는 Java 스타일의 get_age()보다 property를 더 자주 씁니다.
값 설정 시 규칙이 있으면 setter
값 검증을 호출하는 모든 곳마다 반복하지 않고, 속성 하나에 모아 둘 수 있습니다.
class User:
@property
def age(self) -> int:
return self._age
@age.setter
def age(self, value: int) -> None:
if value < 0:
raise ValueError("invalid age")
self._age = value이 구조는 객체 불변식을 유지하는 데 도움이 됩니다.
계산 결과를 읽기 전용 속성으로 만들 수도 있다
저장된 필드를 그대로 보여 주는 것뿐 아니라, 다른 속성에서 계산된 값을 읽기 전용으로 노출할 때도 유용합니다.
class Rect:
def __init__(self, width: int, height: int) -> None:
self.width = width
self.height = height
@property
def area(self) -> int:
return self.width * self.height이때는 setter 없이 getter만 두어 계산 속성임을 드러낼 수 있습니다.
구조 비교
단순 공개 필드가 더 나은 경우도 있다
모든 속성을 property로 감싸는 건 Python답지 않을 때도 많습니다. 검증도 계산도 부작용도 없다면 그냥 공개 속성이 더 단순합니다.
즉 property는 "항상 쓰는 기본형"이 아니라, 속성 문법을 유지하면서 로직을 숨길 가치가 있을 때 꺼내는 도구입니다.
주의할 점
property 안에서 자기 자신 속성을 다시 대입하면 재귀 호출이 생길 수 있습니다. 내부 저장용 이름을 분리해야 합니다.
# ❌ setter 안에서 self.age를 다시 대입
class User:
@property
def age(self):
return self.age
@age.setter
def age(self, value):
self.age = value
# ✅ 내부 저장소는 _age처럼 분리
class User:
@property
def age(self):
return self._age
@age.setter
def age(self, value):
self._age = value참고 링크
2 sources