datarekha
Python Easy Asked at GoogleAsked at AmazonAsked at MicrosoftAsked at Airbnb

How does the `@property` decorator work in Python, and when should you prefer it over a plain attribute?

The short answer

`@property` turns a method into a descriptor that Python calls automatically on attribute access, letting you add validation or computation behind a dot-access interface without changing callers. Use it when a value is derived, needs guarding, or must be lazily computed — not as a default for every attribute.

How to think about it

This question is testing whether you understand Python’s descriptor protocol and the design principle behind it. The real point: @property lets you start with a plain attribute and add behaviour later — validation, computation, caching — without changing a single line of code that calls your class.

Without @property, the only way to guard an attribute is to rename it to set_radius() and get_radius(), which forces every caller to update. With @property, c.radius = 5 still works but now runs your validation code invisibly.

A runnable walkthrough

How it works under the hood

@property creates a descriptor object attached to the class. When Python sees c.radius on the right-hand side of an assignment, it calls the descriptor’s __get__ method (your getter). When it sees c.radius = value, it calls __set__ (your setter). The private backing attribute _radius stores the actual value; the property mediates all access.

The class-level flow looks like this:

c.radius        →  Circle.radius.__get__(c, Circle)   →  return c._radius
c.radius = 10   →  Circle.radius.__set__(c, 10)       →  validate + store c._radius = 10

When to use it

Use @property for derived values (like area or diameter), validated assignments, and lazy computation. Do not wrap every plain attribute in a property “just in case” — it adds overhead and noise with no benefit.

Learn it properly Classes & Instances

Keep practising

All Python questions

Explore further

Skip to content