Python
class properties
programming
coding
duplicate question

How to make a class property?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Python, the phrase "class property" is ambiguous. Most people actually mean an instance property created with @property. A true property on the class object itself is a different pattern and usually requires a custom descriptor.

The Common Case: Instance Property

This is the standard @property pattern:

python
1class Circle:
2    def __init__(self, radius):
3        self._radius = radius
4
5    @property
6    def radius(self):
7        return self._radius
8
9    @radius.setter
10    def radius(self, value):
11        if value <= 0:
12            raise ValueError("radius must be positive")
13        self._radius = value
14
15
16c = Circle(3)
17print(c.radius)
18c.radius = 5
19print(c.radius)

This creates a managed attribute on each instance. Access looks like field access, but Python runs the getter and setter methods behind the scenes.

Why @property Is Useful

Properties let you:

  • validate assignments
  • compute values on demand
  • preserve a simple attribute-style API
  • change implementation later without changing calling code

That is why @property is so common for encapsulation.

What a True Class-Level Property Means

Sometimes the goal is this:

python
print(MyClass.some_value)

where some_value is computed like a property on the class itself, not on an instance.

Python's built-in property does not do that out of the box. It is an instance-level descriptor.

Custom Descriptor for Class-Level Access

python
1class classproperty:
2    def __init__(self, func):
3        self.func = func
4
5    def __get__(self, obj, owner):
6        return self.func(owner)
7
8
9class AppConfig:
10    _version = "1.2.3"
11
12    @classproperty
13    def version(cls):
14        return f"version {cls._version}"
15
16
17print(AppConfig.version)

Here version behaves like a read-only computed property on the class.

Class Property Versus Class Variable

Do not confuse a class property with a plain class variable:

python
class AppConfig:
    version = "1.2.3"

This is just a class attribute. It is perfectly fine when you need shared stored data and no special logic.

You only need a property-like mechanism when access should be computed or controlled.

When to Use Each Pattern

Use an instance property when:

  • the value belongs to each object separately
  • validation or computed access is needed on instances

Use a class variable when:

  • one shared stored value is enough
  • no special getter logic is needed

Use a custom class-property descriptor when:

  • the class itself should expose a computed attribute
  • you want attribute-style access on the class object

Consider @classmethod Too

A lot of "class property" requirements are actually clearer as a class method:

python
1class AppConfig:
2    _version = "1.2.3"
3
4    @classmethod
5    def version(cls):
6        return f"version {cls._version}"

Calling AppConfig.version() is explicit and often easier to understand than introducing a custom descriptor.

Common Pitfalls

The biggest mistake is assuming @property creates a property on the class object. It does not. It creates a descriptor for instance access.

Another mistake is using a custom class-property descriptor when a simple class variable or @classmethod would be clearer.

People also forget that descriptors add complexity. If the value is static and simple, plain class attributes are easier.

Finally, if you validate through @property, store the underlying value under a different name such as _radius to avoid infinite recursion.

One more practical rule helps a lot: if you catch yourself building a writable class-property descriptor, stop and ask whether explicit class methods would be clearer. In many codebases, they are.

Summary

  • In Python, @property creates managed attributes on instances, not on the class object itself.
  • Most "class property" questions are really about ordinary instance properties.
  • Use a plain class variable for simple shared data.
  • Use a custom descriptor only when you truly need class-level computed attribute access.
  • Consider @classmethod if explicit method syntax is clearer than descriptor magic.

Course illustration
Course illustration

All Rights Reserved.