Python:ProxyProperties
lastmod 2025-04-25created 2025-04-251 edits
Did you know that a class attribute can be used as both a method and an attribute?!?
This is not a built-in Python feature, but an example of what you can do by making good use of Python's magic methods and descriptors.
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
How does this work? It works through Python's Descriptor Protocol1.
- The
__get__method transforms theProxyPropertyobject 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.
This creates a dual-purpose attribute that can be read directly or called like a function!
The advantage of this class is that it lets you build intuitive APIs where an attribute needs configuration or should have sensible defaults but can still be customized.
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
- [Recommended] Advanced Python features | GeekNews
- [Original] 14 Advanced Python Features | Edward Li's Blog 2
References
-
14_Advanced_Python_Features_-_Edward_Li's_Blog.pdf ↩