Your problem is fixed like this:
class Blah1:
atttr = 5
class Blah2(Blah1):
aa = BLah1.atttr
However, as pointed out in the comments, this is a weird thing to do. Now you have this:
>>> ob = Blah2()
>>> assert ob.aa == ob.atttr
True
EDIT: As stated in wim's answer, the cause of this is how scoping works inside of a class definition. When you do this:
class C():
a = 1
It is pretty much equivalent to this:
C = type('C', (), {}) # <--- dynamic class creation function
C.a = 1
As you can see, in order to access that a
anywhere outside of the class definition body, you have to refer to it using the class (or an instance of the class): C.a
or c().a
. But note this "gotcha":
class C():
a = 1
c = C()
c.a = 2
print(C.a) # prints 1!!!
It prints 1 because after the second line above, there is now both a c
attribute a
and a C
attribute a
, and they are two different objects:
>>> vars(c)
{'a': 2}
>>> vars(C)
{'a': 1}
If you want c.a
to not override C.a
, you need to learn about properties and descriptors. Maybe start here.