bad_gravitas
bad_gravitas

Reputation: 1

python inheritance and/or descriptors differences in 2.7 and 3

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

Answers (1)

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

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

Related Questions