You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
@classmethod can be stacked on @property, but @staticmethod cannot #89136
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/rhettinger'closed_at=<Date2021-08-22.17:25:36.323>created_at=<Date2021-08-22.06:39:43.790>labels= ['type-feature', '3.9', '3.10', '3.11']
title='@classmethod can be stacked on @property, but @staticmethod cannot'updated_at=<Date2021-08-22.17:38:02.202>user='https://github.com/tusharsadhwani'
The classmethod and staticmethod decorators have somewhat different semantics. Accessing a classmethod with C.cm creates a bound method object which has both __call__ and __get__. In contrast, accessing a staticmethod with C.sm returns the underlying function. So there is no opportunity for a customized __get__ method as we have with classmethod.
Also, even if C.sm did return a custom descriptor, the code example still can't be made to work because the __get__ method on property objects is hardwired to pass in an instance.¹ That means that the underlying method must have a "self" argument.
Another issue is that properties have __set__ and __delete__ methods which could not be made to work without a reference to the class or instance.
To make a read-only class variable, a metaclass would be needed. While it is possible to write a descriptor to make C.FINE_STRUCTURE_CONSTANT call a function that returns 1/137, there is no way for the descriptors to block the assignment: C.FINE_STRUCTURE_CONSTANT = 1 / 100
Thanks for the suggestion, but I don't think this can be made to work.
Activity
tusharsadhwani commentedon Aug 22, 2021
Starting with Python3.9,
@classmethodcan be stacked on top of@property, but it seems that@staticmethodcannot.This feels like inconsistent behaviour, plus, having staticmethod properties can be useful for creating read-only class attributes, for eg:
This would make it hard to accidentally modify the constant inside the class.
rhettinger commentedon Aug 22, 2021
The classmethod and staticmethod decorators have somewhat different semantics. Accessing a classmethod with C.cm creates a bound method object which has both __call__ and __get__. In contrast, accessing a staticmethod with C.sm returns the underlying function. So there is no opportunity for a customized __get__ method as we have with classmethod.
Also, even if C.sm did return a custom descriptor, the code example still can't be made to work because the __get__ method on property objects is hardwired to pass in an instance.¹ That means that the underlying method must have a "self" argument.
Another issue is that properties have __set__ and __delete__ methods which could not be made to work without a reference to the class or instance.
To make a read-only class variable, a metaclass would be needed. While it is possible to write a descriptor to make C.FINE_STRUCTURE_CONSTANT call a function that returns 1/137, there is no way for the descriptors to block the assignment: C.FINE_STRUCTURE_CONSTANT = 1 / 100
Thanks for the suggestion, but I don't think this can be made to work.
¹ https://docs.python.org/3/howto/descriptor.html#properties