So I have some god forsaken legacy code that uses the reserved word property
, um wrong. In a base class that gets inherited they have basically implemented.
class TestClass(object):
def __init__(self, property):
self._property = property
@property
def property(self):
return self._property
test = TestClass('test property')
print(test.property)
Which runs without error. If you add another method below that you get,
class TestClass2(object):
def __init__(self, property):
self._property = property
@property
def property(self):
return self._property
@property
def other_property(self):
return 'test other property'
test = TestClass2('test property')
print(test.property)
print(test.other_property)
Which throws:
---> 10 @property
11 def other_property(self):
12 print('test other property')
TypeError: 'property' object is not callable
Because you know you have overwritten property
in the local namespace.
class TestClass3(object):
def __init__(self, property):
self._property = property
@property
def other_property(self):
return 'test other property'
@property
def property(self):
return self._property
test = TestClass3('test property')
print(test.property)
print(test.other_property)
You can work around this if you always define your property
overwrite at the bottom of your class. If the property
method is only defined on the base class you inherit from things also work out, because namespaces.
class TestClass4(TestClass):
def __init__(self, property):
super(TestClass4, self).__init__(property)
@property
def other_property(self):
return 'test other property'
test = TestClass4('test property')
print(test.property)
print(test.other_property)
My righteous indignation says that we MUST update this variable name in the huge amount of legacy code, because GAAAAH, but other than having to remember to add new methods above the definition of property
definition in the rarely modified base class, this doesn't actually break anything right?
dont shadow builtins... with almost no refactoring at all you can avoid shadowing the builtin entirely
use __getattr__
instead of @property
to return your _property
member ...
class TestClass(object):
def __init__(self):
self._property = 12
def __getattr__(self,item):
if item == "property":
#do your original getter code for `property` here ...
# now you have not overwritten the property keyword at all
return getattr(self,"_property") # just return the variable
class TestClass2(TestClass):
def __init__(self):
self._property = 67
print TestClass2().property
class MySubClass(TestClass):
@property
def a_property(self):
return 5
print MySubClass().property
print MySubClass().a_property
really, as an aside, theres not any good reason imho to use @property
in python. all it does is end up confusing other programmers later and obscuring the fact that you are actually calling a function. I used to do it regularly ... I now avoid it unless I have a very very compelling reason not to
Yes, if you always add new methods above the definition of the property
method nothing will break. So put a nice big comment to that effect in the code. Hopefully, anyone wanting to override property
in a derived class will look at the base class first and see your comment...
BTW, the property
arg to the __init__
method also shadows property
, but I guess that's not an issue.
Ideally, someone should clean this mess up, but I understand that it may not be cost-effective to do that.
Also, I'm somewhat baffled why the original coder made property
an @property in the first place. That construct should only be used when the value of the attribute has to be calculated dynamically, not for simply returning a static attribute. Perhaps they were new to Python and they were told that's the way to do getters in Python...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With