파이썬의 속성(property)은 다른 언어(Java/C++)의 getter 및 setter와 유사하게 속성의 캡슐화를 우아하게 구현하는 방법으로 등장했지만, 메서드를 명시적으로 호출할 필요는 없습니다. property가 없던 시절에는 변수를 접근하기 위해 명시적인 메서드 get/set을 구현해야 했기 때문에 클래스 인터페이스가 복잡해졌습니다.
문제는 클래스 사용자가 속성과의 작업을 투명하게 인터페이스할 수 있도록(dot 표기법 obj.x를 사용하여) 하면서 내부적으로는 계산, 검증, 캐싱 또는 값의 유효성을 제어할 수 있어야 한다는 것입니다. property가 없다면 내부 구현이 변경될 때 모든 호출을 변경해야 하므로 대량의 오류가 발생하고 확장성이 떨어집니다.
해결책은 @property 데코레이터를 사용하여 메서드를 속성으로 변환하고 계산, 검증 또는 지연 로딩의 로직을 메서드 안에 숨기는 것입니다. getter는 읽기 전용으로 구현되고, .setter를 사용하여 쓰기를 관리하며, .deleter를 사용하여 삭제를 처리합니다.
코드 예제:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): # 'area'는 이제 속성처럼 읽을 수 있음 return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): # rect.width = ... 할 때 자동으로 호출됨 assert value > 0, "Width must be positive" self._width = value rect = Rectangle(3, 4) print(rect.area) # 12 rect.width = 10 print(rect.area) # 40
주요 특징:
property가 클래스 메서드나 정적 메서드와 함께 작동할 수 있습니까?
아니요. property는 인스턴스 수준(instance-level)의 속성만을 처리합니다. 클래스 수준(class-level)에서는 특별한 기술자(descriptor)나 @classmethod-property를 사용해야 합니다(수동으로 구현됨).
setter 없이 getter만 있는 property를 선언하면 속성에 값을 쓸 수 있습니까?
아니요. 그런 property는 읽기 전용(read-only)입니다; 할당 시도는 AttributeError를 발생시킵니다.
setter 내부에서 예외가 발생하면(예: assert)?
예외가 외부로 전파되고, 할당은 이루어지지 않으며, 속성의 값은 이전 상태를 유지합니다. 이는 검증을 위해 자주 사용됩니다.
부정적인 사례: 클래스의 공개 속성을 제어 없이 변경.
장점: 빠르고 간단함.
단점: 클라이언트 코드를 다시 작성하지 않고 내부 로직을 변경할 수 없으며, 일관되지 않은 상태가 발생할 수 있습니다.
긍정적인 사례: property를 통한 캡슐화, getter/setter의 로직, 엄격한 검증.
장점: 유연성, 제어, 투명성, 안전한 API 진화.
단점: 코드가 약간 더 많고, 디버깅이 다소 복잡해질 수 있습니다.