Because in Python you have properties:
class Foo:
def __init__(self, value):
self.__value = value
@property
def value(self):
return self.__value
@value.setter
def set_value(self, that):
if that < 0:
self.__value = 0
else:
self.__value = that
Properties make it appear that you are dealing with an attribute but in fact, you're dealing with setters and getters. This allow for better useage of one of Python's defining traits: Duck Typing.
Hence, I can do the following:
class Bar:
def __init__(self, value, other):
self.value = value
self.other = other
def __str__(self):
return ''.join(['Oh joy', str(self.value), str(self.other), '!'])
And then in the function:
def stuff(x):
return x.value + 1
I could pass either a type of Bar
or a type of Foo
and it wouldn't matter. Duck typing would let it "just work."