Like I always did before 3.9, nonetheless: a custom "property" rewrite.

The problem is, "property" does a lot of things, and if one will need everything its in there, it is a lot of code.

I guess it is possible to just subclass property itself, so that we can get an extra .class_getter decorator.

A class setter, obviously, would involve either a custom metaclass or an especialisation of __setattr__.

Let's see if I can come with a reasonably short classproperty.

[after tinkering a bit]

So, it turns out simply inheriting property and adding a decorator for a "class getter" is not easily feasible - "property" is not written with subclassing and expanding its functionality in mind.

Therefore, the "easy" thing, and subset is to write a custom descriptor decorator, which will just convert a single method into a classgetter - and no set, del or inheritance support at all.

On the other hand, the code is short and simple:

class classproperty:
    def __init__(self, func):
        self.fget = func
    def __get__(self, instance, owner):
        return self.fget(owner)

And this simply works as expected:


In [19]: class A:
    ...:     @classproperty
    ...:     def test(cls):
    ...:         return f"property of {cls.__name__}"
    ...: 

In [20]: A.test
Out[20]: 'property of A'

Another way, if one wants to go all the way to have a class attribute setter, it is a matter of writing a plain property on a custom metaclass (which can exist just for holding the desired properties). This approach however will render the properties invisible on the instances - they will work only on the class itself:


In [22]: class MetaA(type):
    ...:     @property
    ...:     def test(cls):
    ...:         return cls._test
    ...:     @test.setter
    ...:     def test(cls, value):
    ...:         cls._test = value.upper()
    ...: 

In [23]: class A(metaclass=MetaA):
    ...:     pass
    ...: 

In [24]: A.test = "hello world!"

In [25]: A.test
Out[25]: 'HELLO WORLD!'

In [26]: A().test
--------------------------------------------------------------
...
AttributeError: 'A' object has no attribute
Answer from jsbueno on Stack Overflow
Top answer
1 of 3
12

Like I always did before 3.9, nonetheless: a custom "property" rewrite.

The problem is, "property" does a lot of things, and if one will need everything its in there, it is a lot of code.

I guess it is possible to just subclass property itself, so that we can get an extra .class_getter decorator.

A class setter, obviously, would involve either a custom metaclass or an especialisation of __setattr__.

Let's see if I can come with a reasonably short classproperty.

[after tinkering a bit]

So, it turns out simply inheriting property and adding a decorator for a "class getter" is not easily feasible - "property" is not written with subclassing and expanding its functionality in mind.

Therefore, the "easy" thing, and subset is to write a custom descriptor decorator, which will just convert a single method into a classgetter - and no set, del or inheritance support at all.

On the other hand, the code is short and simple:

class classproperty:
    def __init__(self, func):
        self.fget = func
    def __get__(self, instance, owner):
        return self.fget(owner)

And this simply works as expected:


In [19]: class A:
    ...:     @classproperty
    ...:     def test(cls):
    ...:         return f"property of {cls.__name__}"
    ...: 

In [20]: A.test
Out[20]: 'property of A'

Another way, if one wants to go all the way to have a class attribute setter, it is a matter of writing a plain property on a custom metaclass (which can exist just for holding the desired properties). This approach however will render the properties invisible on the instances - they will work only on the class itself:


In [22]: class MetaA(type):
    ...:     @property
    ...:     def test(cls):
    ...:         return cls._test
    ...:     @test.setter
    ...:     def test(cls, value):
    ...:         cls._test = value.upper()
    ...: 

In [23]: class A(metaclass=MetaA):
    ...:     pass
    ...: 

In [24]: A.test = "hello world!"

In [25]: A.test
Out[25]: 'HELLO WORLD!'

In [26]: A().test
--------------------------------------------------------------
...
AttributeError: 'A' object has no attribute
2 of 3
0

I think this is a very good question, and I wish it had a better answer. My favourite approach that I was able to find was using __init_subclass__ from this answer.

🌐
Python.org
discuss.python.org › python help
Abstract, generic class properties beyond Python 3.13 - Python Help - Discussions on Python.org
May 13, 2024 - Up until now (Python 3.12) I’ve ... @abstractmethod def handle(self, msg: Msg[DataIn]): ... And it all type checks and works great, but: # Class properties are deprecated in Pytho......
Discussions

classmethod properties are removed in Python 3.13
Deprecated since version 3.11, removed in version 3.13: Class methods can no longer wrap other descriptors such as property(). ... ____________________________ test_native_functions _____________________________ def test_native_functions(): # Note, these assertions might need to be changed for new versions of zstd > assert Zstd.default_level == 3 E AssertionError: assert More on github.com
🌐 github.com
3
July 21, 2024
0.981 `@classmethod` and `@property` can no longer be chained
Class properties were introduced in Python 3.9, and used to be unanalysed in 0.971: # mypy 0.971 class A: @property @classmethod def bad_class_property(cls) -> int: # No mypy error return 8 @cla... More on github.com
🌐 github.com
2
August 10, 2022
Creation of dynamic property deprecated
The best solution if possible is to stop using dynamic properties and instead define them on the class - it can help prevent bugs, and has performance/memory benefits too. However; if that is not possible because dynamic properties are too embedded in your architecture, you can reenable dynamic properties on a class with the AllowDynamicProperties attribute: https://www.php.net/manual/en/class.allowdynamicproperties.php More on reddit.com
🌐 r/PHPhelp
4
1
February 3, 2023
3.13 class properties
https://docs.python.org/3.13/whatsnew/3.13.html#builtins More on reddit.com
🌐 r/learnpython
7
4
October 18, 2024
🌐
Reddit
reddit.com › r/learnpython › 3.13 class properties
r/learnpython on Reddit: 3.13 class properties
October 18, 2024 -

In 3.13

@classmethod @property def func...

Stopped working. Why was this functionally removed? What was the goal of removing it or what under the hood changed that made this impossible? Is there any alternative or workaround?

🌐
GitHub
github.com › zarr-developers › numcodecs › issues › 553
classmethod properties are removed in Python 3.13 · Issue #553 · zarr-developers/numcodecs
July 21, 2024 - However, as of Python 3.11, using classmethod on property was deprecated, and has been removed in Python 3.13: https://docs.python.org/3.13/library/functions.html#classmethod
Author   QuLogic
🌐
Readthedocs
deprecated.readthedocs.io › en › latest › introduction.html
Introduction — Deprecated 1.3.1 documentation
The Python Deprecated Library provides a @deprecated decorator to deprecate a class, method or function.
🌐
GitHub
github.com › python › mypy › issues › 13746
0.981 `@classmethod` and `@property` can no longer be chained · Issue #13746 · python/mypy
August 10, 2022 - Class properties were introduced in Python 3.9, and used to be unanalysed in 0.971: # mypy 0.971 class A: @property @classmethod def bad_class_property(cls) -> int: # No mypy error return 8 @classmethod @property def good_class_property(cls) -> int: # No mypy error return 8 ·
Author   bzoracler
🌐
Python
peps.python.org › pep-0702
PEP 702 – Marking deprecations using the type system | peps.python.org
Any syntax that indirectly triggers a call to the function. For example, if the __add__ method of a class C is deprecated, then the code C() + C() should trigger a diagnostic. Similarly, if the setter of a property is marked deprecated, attempts to set the property should trigger a diagnostic.
🌐
PyPI
pypi.org › project › Deprecated
Deprecated · PyPI
Python @deprecated decorator to deprecate old python classes, functions or methods.
      » pip install Deprecated
    
Published   Oct 30, 2025
Version   1.3.1
Find elsewhere
🌐
Twisted
docs.twisted.org › en › twisted-21.7.0 › api › twisted.python.deprecate.html
twisted.python.deprecate : API documentation
Return a decorator that marks a property as deprecated. To deprecate a regular callable or class, see deprecated.
🌐
Python
docs.python.org › 3 › library › abc.html
abc — Abstract Base Classes
This special case is deprecated, as the property() decorator is now correctly identified as abstract when applied to an abstract method: class C(ABC): @property @abstractmethod def my_abstract_property(self): ...
🌐
kafues511
kafues511.jp › ホーム › class properties are deprecated in python 3.11 and will not be supported in python 3.13
Class properties are deprecated in Python 3.11 and will not be supported in Python 3.13 - kafues511
October 25, 2024 - This can no longer be used to wrap other descriptors such as property. The core design of this feature was flawed and caused a number of downstream problems. To “pass-through” a classmethod, consider using the wrapped attribute that was added in Python 3.10.
🌐
Hanspeterschaub
hanspeterschaub.info › basilisk › Documentation › utilities › deprecated.html
deprecated — Basilisk 2.4.0 documentation
If you want to deprecate myProperty in the following class: class MyClass: @property def myProperty(self): return 0 @myProperty.setter def myProperty(self, value: int): ... ... class PythonTest: @property def myProperty(self): return 0 @myProperty.setter def myProperty(self, value: int): ...
🌐
JetBrains
jetbrains.com › help › inspectopedia › PyDeprecation.html
Deprecated function, class, or module | Inspectopedia Documentation
March 12, 2025 - Reports usages of Python functions, or methods that are marked as deprecated and raise the DeprecationWarning or PendingDeprecationWarning warning. Also, this inspection highlights usages of abc.abstractstaticmethod, abc.abstractproperty, and abc.abstractclassmethod decorators. ... class Foo: @property def bar(self): import warnings warnings.warn("this is deprecated", DeprecationWarning, 2) return 5 foo = Foo() print(foo.bar)
🌐
Python
docs.python.org › 3 › deprecations › index.html
Deprecations — Python 3.14.3 documentation
When using the functional syntax of TypedDicts, failing to pass a value to the fields parameter (TD = TypedDict("TD")) or passing None (TD = TypedDict("TD", None)) has been deprecated since Python 3.13.
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-47615 › Support-combining-classmethod-and-property
Support combining @classmethod and @property
{{ (>_<) }} This version of your browser is not supported. Try upgrading to the latest stable version. Something went seriously wrong
🌐
YouTube
youtube.com › shorts › qeL2ZZpUk30
You can create CLASS properties?! #python #coding #howto - YouTube
If you want to see more of me, join my Discord server!https://discord.gg/5vVgQpKI get a lot of people asking, so here's my setup!• Visual Studio Code: https:...
Published   August 2, 2024
🌐
Python.org
discuss.python.org › peps
PEP 702: Marking deprecations using the type system - Page 2 - PEPs - Discussions on Python.org
March 29, 2023 - I present PEP 702, which proposes to add an @typing.deprecated decorator that provides a way to communicate to static type checkers about deprecated functionality. Let me know if you have any thoughts on this proposal…
🌐
DEV Community
dev.to › hckjck › python-deprecation-2mof
Python deprecation - DEV Community
February 9, 2023 - One obvious quick fix is to write the deprecation warning and hardcode the deprecated class name. warn( f"{cls.__name__} inherits from ADeprecatedClass which has been deprecated.
🌐
Readthedocs
deprecated.readthedocs.io › en › latest › tutorial.html
Tutorial — Deprecated 1.3.1 documentation
In other word, deprecating a class is the same as deprecating it’s __new__ class method. As a reminder, the magic method __new__ will be called when instance is being created. Using this method you can customize the instance creation. the deprecated() decorator patches the __new__ method in order to emmit the warning message before instance creation.