Inside of DFoo
, you cannot refer to Foo._BAR
without referring to Foo
. Python variables are searched in the local, enclosing, global and built-in scopes (and in this order, it is the so called LEGB rule) and _BAR
is not present in any of them.
Let's ignore an explicit Foo._BAR
.
Further, it gets inherited: DFoo._BAR
will be looked up first in DFoo
, and when not found, in Foo
.
What other means are there to get the Foo
reference? Foo
is a base class of DFoo
. Can we use this relationship? Yes and no. Yes at execution time and no at definition time.
The problem is when the DFoo
is being defined, it does not exist yet. We have no start point to start following the inheritance chain. This rules out an indirect reference (DFoo
-> Foo
) in a def method(self, ....):
line and in a class attribute _DBAR = _BAR
.
It is possible to work around this limitation using a class decorator. Define the class and then modify it:
def deco(cls):
cls._BAR = cls.__mro__[1]._BAR * 2 # __mro__[0] is the class itself
return cls
class Foo:
_BAR = 10
@deco
class DFoo(Foo):
pass
print(Foo._BAR, DFoo._BAR) # 10 20
Similar effect can be achieved with a metaclass.
The last option to get a reference to Foo
is at execution time. We have the object self
, its type is DFoo
, and its parent type is Foo
and there exists the _BAR
. The well known super()
is a shortcut to get the parent.
I have assumed only one base class for simplicity. If there were several base classes, super()
returns only one of them. The example class decorator does the same. To understand how several bases are sorted to a sequence, see how the MRO works (Method Resolution Order).
My final thought is that I could not think up a use-case where such access as in the question would be required.