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
