Reputation: 3
I wrote below code with python 3.6.
class A:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
@property
def p1(self):
return self._p1
@p1.setter
def p1(self, p1):
self._p1 = p1
@property
def p2(self):
return self._p2
@p2.setter
def p2(self, p2):
self._p2 = p2
class B(A):
def __init__(self, p1, p2, p3):
super(B, self).__init__(p1, p2)
self.p3 = p3
@property
def p1(self):
return self._p1 if self.p3 is None else self._p1+1
@property
def p3(self):
return self._p3
@p3.setter
def p3(self, p3):
self._p3 = p3
b1 = B(1,2,3)
When create instance with class B 'AttributeError: can't set attribute'
occurred. How do I fix it?
Upvotes: 0
Views: 5627
Reputation: 532043
The problem is that in B
, you've overriden the entire property p1
, not just the getter of A
's property by the same name. You need to provide the setter explicitly.
class B(A):
...
# Not sure if there is a better method than
# simply copying this from A. (At least,
# not without creating your own custom property
# descriptor that supports inheritance.)
@p1.setter
def p1(self, x):
self._p1 = x
Upvotes: 2
Reputation: 40773
The problem is in class B, you only have the property for p1
, without a setter. That makes p1
a read-only property. In class A, at the line:
self.p1 = p1
you will get the AttributeError
because you are trying to overwrite a read-only property. The fix is to add a setter for class B:
@p1.setter
def p1(self, p1):
print('Setting B.p1 = {}'.format(p1))
self._p1 = p1
With this addition, re-run your code and you will notice the print output. Once happy, you can remove that print line.
Upvotes: 1
Reputation: 14273
You need to define @p1.setter also for class B
class A:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
@property
def p1(self):
return self._p1
@p1.setter
def p1(self, p1):
self._p1 = p1
@property
def p2(self):
return self._p2
@p2.setter
def p2(self, p2):
self._p2 = p2
class B(A):
def __init__(self, p1, p2, p3):
super(B, self).__init__(p1, p2)
self.p3 = p3
@property
def p1(self):
return self._p1 if self.p3 is None else self._p1+1
@p1.setter
def p1(self, p1):
self._p1 = p1
@property
def p3(self):
return self._p3
@p3.setter
def p3(self, p3):
self._p3 = p3
b1 = B(1, 2, 3)
b2 = B(1, 2, None)
print(b1.p1)
print(b2.p1)
output
2
1
Upvotes: 2