파이썬에서 **캡슐화(encapsulation)**를 구현할 때 가장 많이 쓰이는 도구 중 하나가 @property입니다.
이를 통해 객체의 속성에 안전하게 접근할 수 있고, 필요하다면 검증 로직까지 넣을 수 있습니다.
그런데 초보자분들이 자주 혼동하는 부분이 있습니다.
바로 "@property는 인스턴스 변수용인가, 클래스 변수에도 쓸 수 있는가?" 하는 문제입니다.
1. @property는 인스턴스 변수를 위한 기능
@property와 @속성이름.setter는 인스턴스 변수를 대상으로 동작합니다.
즉, 객체가 가지고 있는 self._변수를 감싸서 getter와 setter를 제공하는 방식입니다.
예시
class Car:
def __init__(self, price):
self._price = price # 인스턴스 변수
@property
def price(self): # getter
return self._price
@price.setter
def price(self, value): # setter
if value < 0:
raise ValueError("가격은 0 이상이어야 합니다.")
self._price = value
사용 예시:
car = Car(1000)
print(car.price) # getter 동작 → 1000
car.price = 2000 # setter 동작
print(car.price) # 2000
car.price = -500 # ValueError 발생
외부에서는 car.price처럼 속성에 접근하지만, 내부적으로는 _price라는 인스턴스 변수가 보호되고 있습니다. 이것이 파이썬에서 말하는 캡슐화입니다.
2. setter는 반드시 property가 정의되어 있어야 한다
중요한 점은, setter는 @property가 먼저 정의되어 있어야만 사용 가능하다는 것입니다.
class Car:
@price.setter # ❌ 오류: 아직 price라는 property 없음
def price(self, value):
self._price = value
위 코드를 실행하면 NameError가 발생합니다.
@price.setter는 price라는 property 객체에 setter를 연결하려는 문법인데,
정작 @property def price(self)가 없으니 당연히 동작하지 않는 것이죠.
따라서 setter를 쓰려면 반드시 아래처럼 **getter(@property)**가 먼저 정의되어야 합니다.
class Car:
def __init__(self, price):
self._price = price
@property
def price(self): # getter
return self._price
@price.setter
def price(self, value): # setter
self._price = value
3. 클래스 변수에는 @property를 쓰지 않는다
많이 혼동하는 부분이 클래스 변수입니다.
예를 들어, 아래처럼 클래스 차원에서 공유되는 변수를 관리하고 싶을 수 있습니다.
class Car:
price_per_raise = 1.0 # 클래스 변수
이런 경우에는 @property를 직접 붙이면 의도대로 동작하지 않습니다.
왜냐하면 @property는 기본적으로 **인스턴스 속성(self)**을 전제로 하기 때문입니다.
클래스 변수를 제어하고 싶다면 다음 두 가지 방법이 일반적입니다.
1️⃣ 방법 1. 클래스 메소드 사용
class Car:
price_per_raise = 1.0
@classmethod
def set_price_per_raise(cls, per):
if per <= 1:
raise ValueError("1보다 큰 값을 넣어야 합니다.")
cls.price_per_raise = per
2️⃣ 방법 2. 인스턴스 property에서 클래스 변수 참조
class Car:
_price_per_raise = 1.0
@property
def price_per_raise(self):
return self.__class__.price_per_raise
@price_per_raise.setter
def price_per_raise(self, per):
if per <= 1:
raise ValueError("1보다 큰 값을 넣어야 합니다.")
self.__class__.price_per_raise = per
이렇게 하면 인스턴스에서 접근할 때 car.price_per_raise처럼 보이지만, 실제로는 클래스 변수(Car.price_per_raise)가 수정됩니다.
정리하면
- @property, @속성이름.setter는 인스턴스 변수 전용이다.
- setter는 반드시 @property가 먼저 정의되어 있어야 한다.
- 클래스 변수를 관리하려면 @classmethod를 쓰거나, property에서 self.__class__를 통해 우회 접근한다.
결론적으로, @property는 인스턴스 속성 캡슐화 도구이고, 클래스 변수 관리에는 맞지 않습니다
'파이썬 > 클래스와 객체 지향' 카테고리의 다른 글
| 파이썬 네임스페이스(namespace) 쉽게 이해하기 (0) | 2025.09.10 |
|---|---|
| 파이썬에서 __add__와 연산자 재정의 (1) | 2025.09.06 |
| 추상 클래스 제대로 쓰기: 변수·일반 메서드·super() 재사용 (1) | 2025.09.01 |
| 추상화란 무엇인가?? (0) | 2025.09.01 |
| 파이썬 정적 메소드(Static Method) 이해하기 (0) | 2025.08.31 |