Home > Mobile >  Accesing superclass attribute during subclass construction in Python
Accesing superclass attribute during subclass construction in Python

Time:02-07

Is it possible to access superclass's attributes during class construction? Here's my code:

class A:
   x = 1

class B(A):
   x  = 1   # <- error

The increment line x = ... is not valid, because x is not defined at this moment. You may suggest doing it in __init__, but I need to initialize the values before the constructor and want to minimize the code.

The code x = A.x 1 will not work in my case because the A is generated in run-time. So the real code for B looks like

class A:
  x: int

def class_gen(params):
  class SubA(A):
    x = 1
  return SubA

class B(class_gen(some_params)):
  x  = 1

I've found a weird workaround: x = A.__subclasses__()[-1].x 1 (indeed the last subclass of A will be the generated super), but it looks too dirty and unstable.

Another workaround is declaring the a 'stub' class variable:

...
_Stub = class_gen(some_params)
class B(_Stub):
  x = _Stub.x   1

but is it also looks urgly. Is there a better way for a perfectionist?

CodePudding user response:

There's no easy way to do this. Probably the best is to give your B class a metaclass that handles incrementing of the x attribute for you:

class XIncrementerMeta(type):
    def __new__(mcls, name, bases, namespace):
        namespace['x'] = bases[0].x   1
        return super().__new__(mcls, name, bases, namespace)

class B(class_gen("some_params"), metaclass=XIncrementerMeta):
    pass

print(B.x) # prints 2

But I'd suggest that this issue may be a symptom of a bad OOP design. Rather than relying on class attributes and their inheritance, you might want to make A and B instances and their x values instance attributes, rather than class attributes.

CodePudding user response:

I think you can accomplish it by using __new__ in the subclass.

class A:
    x = 1

class B(A):
    def __new__(cls, *args, **kwargs):
        cls.x  = 1
        return super().__new__(cls, *args, **kwargs)

b = B()
print(b.x)  # 2
  •  Tags:  
  • Related