`super` at class level

I have a hierarchy of classes, all of which use a class variable with the same name. The value of this variable in subclasses depend on the value in the parent class:

class A:
    myclsvar = 5

class B(A):
    myclsvar = A.myclsvar + 2

class C(B):
    myclsvar = B.myclsvar + 4

class D(A):
    myclsvar = A.myclsvar + 1

The above is how I have currently implemented it, but it feels fragile. If I decide to change C’s parent from B to D, I need to remember to also change the definition of C.myclsvar. I would prefer a super-like mechanism to refer to the parent class, but of course super only works inside methods.

Is there something like super that works at the class level?

Is what I’m doing here a Bad Idea™ for some reason, and if so is there a better way to achieve something similar?

Offhand, I don’t see a straightforward way to do this while the class body is executing. At that point, the class doesn’t exist yet, so there is no way to get to its MRO. You can get to its __qualname__ which is in the body’s locals() namespace, but that’s it.

class B(A):
    globals()['B'] # This a fails with a KeyError because B has not been assigned

class B(A):
    print(repr(locals()['__qualname__']))  # This prints the string 'B'

Just after the class is created and just before it is assigned to the enclosing locals namespace, the __set_name__ method is called. At that point you can get to the class and its MRO. Then you can perform a delayed evaluation:

class DeferSuper:
    def __init__(self, expr):
        self.expr = expr
    def __set_name__(self, owner, name):
        ns = {name: getattr(super(owner, owner), name)}
        result = eval(self.expr, ns)
        setattr(owner, name, result)

class A:
    x = 10

class B(A):
    x = DeferSuper('x + 1')

# A.x is 10 and B.x is 11

The next possible attach point is to use a class decorator which will have full access to the class and its MRO. A delayed evaluation on the expression would still be needed.



Thanks Raymond! I hadn’t seen the deferred evaluation technique before, very interesting.

1 Like