4
votes

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?

2
print d will obviously fail because d is not defined. Besides this is not the recommended way to do inheritance, see @Jake77's answer - nluigi
The inherited class attributes aren't available until after the definition completes, unless you access them directly at e.g. A.a - jonrsharpe
To bring the discussion back up to the question - could you edit to show a more useful example of what you're trying to achieve? This is likely an XY problem. - jonrsharpe
We don't normally use Python classes in the way that you're attempting to do. You should be creating instances of your classes, and manipulating the instance attributes inside the instances' methods. Doing arithmetic directly on class attributes outside a method definition looks plain weird, and although it is a permissible way to initialize class attributes, it's certainly not recommended as a general calculation technique. - PM 2Ring
Your new code still doesn't help us to understand what you're really trying to do. And it doesn't show us how you're attempting to use classes, so we can't explain what's wrong with you're current approach. I suspect that you probably don't even need classes, but it's hard to tell from the information you have supplied so far. - PM 2Ring

2 Answers

8
votes

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!

4
votes

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