Python:ProxyProperties
클래스 속성을 메서드와 속성 모두로 사용할 수 있다는 사실, 알고 계셨나요?!?
이는 Python의 기본 기능은 아니지만, Python의 마법 같은 메서드와 설명자를 효과적으로 활용하여 무엇을 할 수 있는지 보여주는 예시입니다.
Code
from typing import Callable, Generic, TypeVar, ParamSpec, Self
P = ParamSpec("P")
R = TypeVar("R")
T = TypeVar("T")
class ProxyProperty(Generic[P, R]):
func: Callable[P, R]
instance: object
def __init__(self, func: Callable[P, R]) -> None:
self.func = func
def __get__(self, instance: object, _=None) -> Self:
self.instance = instance
return self
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
return self.func(self.instance, *args, **kwargs)
def __repr__(self) -> str:
return self.func(self.instance)
def proxy_property(func: Callable[P, R]) -> ProxyProperty[P, R]:
return ProxyProperty(func)
class Container:
@proxy_property
def value(self, val: int = 5) -> str:
return f"The value is: {val}"
# Example usage
c = Container()
print(c.value) # Returns: The value is: 5
print(c.value(7)) # Returns: The value is: 7
이 기능은 어떻게 작동할까요? 파이썬의 설명자 프로토콜(Descriptor Protocol)1 에 따라 작동합니다 .
- The
__get__
method transforms theProxyProperty
object into a descriptor. - When you access
c.value
, Python calls__get__
which returns self (the descriptor instance). - The
__repr__
method handles property access (returning default values). - The
__call__
method handles method calls with parameters.
이렇게 하면 직접 읽을 수도 있고 함수처럼 호출할 수도 있는 이중 용도의 속성이 생성됩니다!
이 클래스의 장점은 속성에 구성이 필요하거나 합리적인 기본값을 가져야 하지만 여전히 사용자 정의가 가능한 직관적인 API를 만들 수 있다는 것입니다.
See also
Favorite site
- Python Descriptors: An Introduction – Real Python
- Demystifying Python’s Descriptor Protocol • DeepSource
- Descriptor Guide — Python 3.13.3 documentation
- Proxies and Wrappers — wrapt 1.17.2 documentation
- [추천] 고급 Python 기능들 | GeekNews
References
-
14_Advanced_Python_Features_-_Edward_Li's_Blog.pdf ↩