It's not method overloading because there aren't two methods with different signatures that can be called. If it was method overloading, you could do something like this:
obj = newOne()
print(obj.val())
obj.val(5)
But that doesn't work, because val
is a property and not an overloaded method.
So what's going on there? Why are we defining two methods with the same name, and what happens to them, if not overloading?
The magic happens in the decorators. As a prerequisite, you have to know that
@deco
def func(...):
...
is equivalent to
def func(...):
...
func = deco(func)
So, the first thing that happens is that the @property
decorator turns your getter function into a property with that function as its getter function:
class newOne:
@property
def val(self):
return self.__x
print(newOne.val)
print(newOne.val.fget)
# output:
# <property object at 0x002B1F00>
# <function newOne.val at 0x0052EAE0>
After this, the @val.setter
decorator creates a new property with a getter and setter function:
class newOne:
@property
def val(self):
return self.__x
@val.setter
def val(self, value):
self.__x = value
print(newOne.val)
print(newOne.val.fget)
print(newOne.val.fset)
# output:
# <property object at 0x0221B7B0>
# <function newOne.val at 0x0226EB70>
# <function newOne.val at 0x0226EAE0>
(The getter and setter functions have the same name because they were both defined as def val(...)
, but they're still different functions. That's why they have different ids.)
So in the end you have a val
property with a getter and a setter function. You do not have an overloaded method.
For details about how properties work and how the getter and setter functions are called, see the descriptor documentation.