Property decorator usage in Python - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
Let's explore how using the property decorator affects the time it takes for a program to run.
We want to know how the program's work changes as the input or usage grows.
Analyze the time complexity of the following code snippet.
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return 3.14159 * self.radius * self.radius
c = Circle(5)
print(c.area)
This code defines a Circle class with a property to calculate area when accessed.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calculating the area each time the property is accessed.
- How many times: Once per access; no loops or recursion involved.
Each time you ask for the area, the program does a fixed number of steps to calculate it.
| Input Size (n) | Approx. Operations |
|---|---|
| 1 (one access) | 3 operations (multiply radius twice and multiply by pi) |
| 10 (ten accesses) | 30 operations (3 operations x 10) |
| 100 (hundred accesses) | 300 operations (3 operations x 100) |
Pattern observation: The work grows directly with how many times you ask for the area.
Time Complexity: O(n)
This means the time grows in a straight line with the number of times you access the property.
[X] Wrong: "Using @property makes the calculation happen only once, so it's always fast."
[OK] Correct: Each time you access the property, the calculation runs again unless you store the result separately.
Understanding how property decorators affect performance helps you write clear and efficient code, a skill valued in many coding challenges.
"What if we changed the property to calculate the area once and save it? How would the time complexity change when accessing the area multiple times?"
Practice
What does the @property decorator do in a Python class?
Solution
Step 1: Understand the role of
The@property@propertydecorator lets you call a method without parentheses, like an attribute.Step 2: Compare options
Only It allows a method to be accessed like an attribute. correctly describes this behavior. Other options describe unrelated features.Final Answer:
It allows a method to be accessed like an attribute. -> Option CQuick Check:
@property makes method act like attribute [OK]
- Thinking @property makes method private
- Confusing @property with @staticmethod
- Believing @property deletes attributes
Which of the following is the correct syntax to define a setter for a property named value?
class MyClass:
@property
def value(self):
return self._value
# What goes here?Solution
Step 1: Identify correct setter syntax
The setter uses the property name with@value.setterand defines a method with the same namevalue.Step 2: Check method name and decorator
@value.setter\ndef value(self, val):\n self._value = val correctly uses@value.setterand methodvalue. Others use wrong decorator or method names.Final Answer:
@value.setter\ndef value(self, val):\n self._value = val -> Option BQuick Check:
Setter uses @propertyname.setter and same method name [OK]
- Using @setter.value instead of @value.setter
- Changing method name in setter
- Using @value.set instead of @value.setter
What will be the output of the following code?
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
self._radius = 0
else:
self._radius = value
c = Circle(5)
c.radius = -3
print(c.radius)Solution
Step 1: Understand setter logic
When settingradius, if value < 0, it sets_radiusto 0, else to value.Step 2: Trace code execution
Initial radius is 5. Thenc.radius = -3triggers setter, sets_radiusto 0. Printingc.radiusreturns 0.Final Answer:
0 -> Option AQuick Check:
Setter sets negative radius to 0 [OK]
- Expecting original value 5 to remain
- Printing -3 instead of 0
- Confusing property with direct attribute
Find the error in this code using property decorators and fix it.
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def set_name(self, value):
self._name = value
p = Person('Alice')
p.name = 'Bob'
print(p.name)Solution
Step 1: Identify setter method name mismatch
The setter decorator@name.setterrequires the method to be namedname, but here it isset_name.Step 2: Fix method name
Rename the setter method tonameto match the property name and decorator.Final Answer:
Change setter method name tonameinstead ofset_name. -> Option AQuick Check:
Setter method name must match property name [OK]
- Using different method name for setter
- Removing @property decorator mistakenly
- Changing attribute name inside setter
Consider a class that stores a temperature in Celsius internally but exposes it as Fahrenheit using property decorators. Which code correctly implements this?
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def fahrenheit(self):
# Convert Celsius to Fahrenheit
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, value):
# Convert Fahrenheit to Celsius
self._celsius = (value - 32) * 5/9
# Usage
temp = Temperature(0)
temp.fahrenheit = 212
print(round(temp._celsius))What is the output?
Solution
Step 1: Understand property getter and setter
The getter converts Celsius to Fahrenheit. The setter converts Fahrenheit back to Celsius and stores it.Step 2: Trace the code
Initially, Celsius is 0. Settingtemp.fahrenheit = 212calls setter, converts 212°F to Celsius: (212-32)*5/9 = 100. Printingtemp._celsiusrounded gives 100.Final Answer:
100 -> Option DQuick Check:
Setter converts Fahrenheit to Celsius correctly [OK]
- Confusing getter and setter conversions
- Printing Fahrenheit instead of Celsius
- Not rounding the output
