If you’re coming from Java, C++, or C#, one of the first things you’ll notice in Python is this:
“Wait… how can I define
def price(self)
anddef price(self, value)
in the same class? Isn’t that illegal?”
Yes — in Java, that’s method overloading.
But in Python? Well… it depends.
In this article, we’ll walk through:
- How method overloading works (and doesn’t work) in Python
- What the
@property
decorator really does - Why
@price.setter
doesn’t overwrite the original method - And how this turns into one of Python’s most elegant features: property binding
🔍 Let’s Start with the Problem
Here’s what doesn’t work in Python:
class Product:
def price(self):
return 100
def price(self, value): # ❌ This will override the first one
self._price = value
❌ Output:
bashCopyEditTypeError: price() missing 1 required positional argument: 'value'
That’s because Python does not support traditional method overloading. The second method with the same name (price
) completely overwrites the first.
🚫 So How Do We Add a Setter?
In Java:
public int getPrice() { return this.price; }
public void setPrice(int value) { this.price = value; }
In Python, we use the @property
decorator:
class Product:
def __init__(self):
self._price = 0
@property
def price(self):
return self._price
@price.setter
def price(self, value):
self._price = value
🧪 What’s Happening Internally?
When you write:
@property
def price(self):
...
Python turns price()
into a property
object, not a method.
Then when you write:
@price.setter
def price(self, value):
...
You’re not defining a new method called price
— you’re telling Python:
“Hey, add this as the
setter
for the existing property calledprice
.”
🧠 No Overloading, Just Property Binding
Here’s what Python does under the hood:
price = property(get_price) # @property
price = price.setter(set_price) # @price.setter
So both the getter and the setter are part of the same property object — there’s no method conflict, no overwriting.
✅ Final Usage
p = Product()
p.price = 99 # Calls setter
print(p.price) # Calls getter
The object looks and behaves like it has a real attribute, but under the hood it’s calling getter
and setter
logic.
✅ Visual Summary
class Product:
@property
def price(self): # READ
return self._price
@price.setter
def price(self, value): # WRITE
self._price = value
Operation | What Happens |
---|---|
p.price | ➜ calls price() getter |
p.price = x | ➜ calls price() setter |
🧩 Bonus: Adding a Deleter
You can even add a deleter!
@price.deleter
def price(self):
del self._price
Now you can do:
del p.price
🚫 Why Not Just Write @setter
?
This is a common beginner mistake:
@setter # ❌ INVALID
def price(self, value): ...
Python wouldn’t know which property this setter is for. That’s why you write:
@price.setter
You’re explicitly saying:
“This is the setter for the
price
property.”
📌 Key Takeaways
- ✅ Python does not support method overloading
- ✅
@property
lets you simulate fields with controlled access - ✅
@price.setter
and@price.deleter
are not new methods, but extensions of the same property - ✅ You can’t define
price()
andprice(value)
as two separate methods — but@property
lets you achieve the same goal cleanly
🧠 Real-Life Use Cases
Use Case | Why Use @property |
---|---|
Validation before assignment | e.g., if value < 0: raise... |
Making attributes read-only | No setter |
Lazy computation | Compute on-demand in getter |
Backward compatibility | Turn methods into fields later |
🏁 Final Thoughts
What looks like method overloading in Python is actually something more elegant: binding multiple behaviors to a single property using decorators.
The @property
pattern is clean, readable, and Pythonic. And unlike Java, you can make your class interface look like attributes while keeping full control over logic.
So no — Python doesn’t support method overloading.
But thanks to @property
, you don’t even need it.
Leave a Reply