2

I am learning OOP in python, and I am surprised to find in another post that a parent class can access a class variable defined in child, like the example below. I can understand that child can access a class variable defined in parent bc of inheritance (or is it not inheritance but something else?). What makes this possible and does it imply a pool of class variables that a subclass can adds to (and its superclasses can access) when it inherits from a superclass?

class Parent(object):
    def __init__(self):
        for attr in self.ATTRS: // accessing class variable defined in child?
            setattr(self, attr, 0)

class Child(Parent):
    #class variable
    ATTRS = ['attr1', 'attr2', 'attr3']

    def __init__(self):
        super(Child, self).__init__()
Community
  • 1
  • 1
Pippi
  • 2,451
  • 8
  • 39
  • 59
  • 1
    You're accessing those variables using `self`. `self` is a direct instance of `Child` not `Parent`, hence it can access those stuff. That's how attribute lookup works. – Ashwini Chaudhary Jul 30 '15 at 20:48
  • is `self` in Parent class you are referring to? – Pippi Jul 30 '15 at 20:50
  • 1
    @Pippi `self` is the *same* instance in both places - it is an instance (an object produced from a class) of whatever class you used to instantiate it (`Child` in this case). From the point of `Child`, it's an instance of itself. From the point of `Parent`, it's an instance of one of its subclasses. – Lukas Graf Jul 30 '15 at 20:53
  • it is `super(Child, self).__init__()`, thanks, so in python, parent can be initiated with child? Does it mean parent have access to child's instance variables and methods? – Pippi Jul 30 '15 at 21:03
  • 1
    @Pippi think of it this way: `self` always means "an instance of myself *or my super- or subclasses*" - so yes, methods on the parent class do have access to instance members (attributes or methods) of its subclasses. I recommend Raymond Hettinger's talk [Python's Class Development Toolkit](https://www.youtube.com/watch?v=HTLu2DFOdTg) on this topic. – Lukas Graf Jul 30 '15 at 21:24
  • 1
    (He addresses this specific case at [34m38s](https://www.youtube.com/watch?v=HTLu2DFOdTg&feature=youtu.be&t=34m38s)) – Lukas Graf Jul 30 '15 at 21:31

2 Answers2

4

The example is a bit twisted. The definition of the parent class is not complete, it references non-existing class variables, which only becomes apparent when instantiating the class or sub-classing it.

If you subclass as follows:

class Child2(Parent):
    def __init__(self):
        super(Child2, self).__init__()

Then instantiating the child class won't work:

Traceback (most recent call last):
  File "./cl.py", line 25, in <module>
    y=Child2()
  File "./cl.py", line 20, in __init__
    super(Child2, self).__init__()
   File "./cl.py", line 6, in __init__
    for attr in self.ATTRS:
AttributeError: 'Child2' object has no attribute 'ATTRS'

You would have to fix your parent as follows to make it work:

class Parent(object):
    ATTRS = None
    def __init__(self):
        if self.ATTRS:
            for attr in self.ATTRS:
                setattr(self, attr, 0)

The reason it works in your original example is that Python is an interpreted language, so the code is only evaluated at run-time.

NZD
  • 1,780
  • 2
  • 20
  • 29
2

The parent is not accessing class variables because the self in __init__(self) is an instance of Child.

Josh J
  • 6,813
  • 3
  • 25
  • 47