Reputation: 1
I'm trying to understand a little more about how python classes and descriptors work. I have the following code.
class Base():
def __init__(self):
self.a = 'base_a'
def get_a(self):
return self._x
def set_a(self,val):
self._x = val
def delete_a(self):
pass
a = property(get_a,set_a,delete_a)
class Derived(Base):
def __init__(self):
Base.__init__(self)
@property
def a(self):
return 'derived_a'
t = Derived()
print(t.a)
Running in Python 2.7, I get
[carl@home tmp-carl]$ python2.7 test.py
base_a
Running in Python 3.3, I get
[carl@home tmp-carl]$ python3 test.py
Traceback (most recent call last):
File "test.py", line 25, in <module>
t = Derived()
File "test.py", line 18, in __init__
Base.__init__(self)
File "test.py", line 5, in __init__
self.a = 'base_a'
AttributeError: can't set attribute
I think I understand the Python3.3 behavior. t is an instance of Derived so Base::__init__
searches for t.__dict__['a']
, doesn't find it. It goes to Derived.__dict__['a']
, finds the read-only property and errors. It never makes it to Base.__dict__['a']
, which is read-write.
But if this is true, I don't understand why Python2.7 works at all. It seems as if it completely ignores the overwritten property in Derived
.
Can anyone explain this to me?
Upvotes: 0
Views: 89
Reputation: 799102
Python 2.x has two types of classes: old-style, and new-style. Descriptors (of which property
is one) only work in new-style classes. In order to create a new-style class in 2.x you must derive from object
.
class Base(object):
All classes in 3.x are new-style classes.
Upvotes: 5