Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing attribute from parent class inside child class

When I access an attribute from the parent class via the child class like this all works fine:

class A():
    a=1
    b=2

class B(A):
    c=3

d=B.a+B.b+B.c
print d

But if I try to access an attribute from the parent class inside the child class like this, it doesn't work:

class A():
    a=1
    b=2

class B(A):
    c=3
    d=a+b+c
    print d

I receive the error: name 'a' is not defined

Let assume that I have many equation like d=a+b+c (but more complicated) and I can't edit them - I have to call in class B "a" as "a", not "self.a" or "something.a". But I can, before equations, do A.a=a. But it is not the smartest way to reload all variables manually. I want to bypass it using inheritance. Is it possible or i should do all manually? Or maybe it is 3th route in this code?

like image 689
Karls Avatar asked Oct 26 '15 12:10

Karls


2 Answers

During the class definition, none of the inherited attributes are available:

>>> class Super(object):
    class_attribute = None
    def instance_method(self):
        pass


>>> class Sub(Super):
    foo = class_attribute



Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    class Sub(Super):
  File "<pyshell#7>", line 2, in Sub
    foo = class_attribute
NameError: name 'class_attribute' is not defined
>>> class Sub(Super):
    foo = instance_method



Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    class Sub(Super):
  File "<pyshell#9>", line 2, in Sub
    foo = instance_method
NameError: name 'instance_method' is not defined

You can't even access them using super, as the name of the subclass isn't defined within the definition block*:

>>> class Sub(Super):
    foo = super(Sub).instance_method



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class Sub(Super):
  File "<pyshell#11>", line 2, in Sub
    foo = super(Sub).instance_method
NameError: name 'Sub' is not defined

The only way to access the inherited attributes at definition time is to do so explicitly, using the name of the superclass:

>>> class Sub(Super):
    foo = Super.class_attribute


>>> Sub.foo is Super.class_attribute
True

Alternatively you can access them within class or instance methods, but then you need to use the appropriate prefix of the class (conventionally cls) or instance (conventionally self) parameter.


* for anyone thinking "ah, but in 3.x you don't need arguments to super":

>>> class Sub(Super):
    foo = super().instance_method


Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    class Sub(Super):
  File "<pyshell#6>", line 2, in Sub
    foo = super().instance_method
RuntimeError: super(): no arguments

That's only true inside instance/class methods!

like image 196
jonrsharpe Avatar answered Sep 28 '22 06:09

jonrsharpe


I may be wrong on this, but are you sure you don't want rather this?

class A(object):
    def __init__(self):
        self.a = 1
        self.b = 2


class B(A):
    def __init__(self):
        super(B, self).__init__()
        self.c = 3

    @property
    def d(self):
        return self.a + self.b + self.c

BB = B()
print BB.d

or, as jonrsharpe pointed out:

class A():
    a=1
    b=2

class B(A):
    c=3
    d=A.a+A.b+c

print B.d
like image 37
jake77 Avatar answered Sep 28 '22 08:09

jake77