What are some alternatives to using classmethod and property decorators together?
In python 3.11 and later, combining them is no longer supported per: https://docs.python.org/3.11/library/functions.html#classmethod
I have code like so:
class Bike:
@classmethod
@property
def tire_type(cls) -> tire_type.Road:
return tire_type.Road
from . import tire_type
tire_type import must be last because it has a cyclic dependency on the current module. What are some options for providing the tire property in the Bike class that does not combine the two decorators?
I also want the tire_type type hint to show up correctly in vscode.
There are a number of solutions. Here are 4 possibilities:
T = typing.TypeVar('T')
class classprop(typing.Generic[T]):
def __init__(self, method: typing.Callable[..., T]):
self.method = method
functools.update_wrapper(self, method) # type: ignore
def __get__(self, obj, cls=None) -> T:
if cls is None:
cls = type(obj)
return self.method(cls)
class Bike:
@classprop
def tire_type(cls) -> typing.Type[tire_type.Road]:
return tire_type.Road
print(Bike.tire_type)
()
are required()
are required@dataclasses.dataclass
class Bike
tire_type: typing.Type[tire_type.Road] = dataclasses.field(
default_factory=lambda: tire_type.Road
)
print(Bike().tire_type)
Option 1 or 4 is preferred because it does not need ()
and it allows a type discriptions of the property and delayed evaluation of the property later when accessing Bike or instantiating it