I have defined a class property by defining an attribute with @property
decorator in a metaclass, as proposed in this SO answer.
As I have only access at the class definition (that will inherits from the metaclass) after it has been defined, I am making it inheriting afterwards, thanks to the trick given in above mentioned SO answer.
I would like the class property defined to be available in both the inheriting class and its instances. But I don't succeed to have it in its instances.
So, let's review my current code:
class TopLevel(type):
""" TopLevel metaclass defining class properties. """
@property
def depth(cls) -> int:
return cls._depth
class OtherClass:
""" Class that will inherit from 'TopLevel' after it has been defined.
Dummy implementation."""
def __init__(self, var):
self.var = var
# Making 'Otherclass' inheriting from metaclass 'TopLevel' to have available
# as class properties 'depth'.
# As per https://stackoverflow.com/a/5121381/4442753
OtherClass = TopLevel(OtherClass.__name__,
OtherClass.__bases__,
dict(OtherClass.__dict__))
# Set a value to '_depth'
OtherClass._depth = 3
# Check OtherClass has 'depth' class property
OtherClass.depth
Out[6]: 3
# Instanciate OtherClass: instance has no 'depth' attribute?
otherclass = OtherClass(4)
otherclass.depth
Traceback (most recent call last):
File "/tmp/ipykernel_748533/2343605532.py", line 1, in <module>
otherclass.depth
AttributeError: 'OtherClass' object has no attribute 'depth'
Can this be achieved?
Edit
Code snippet illustrating my answer to @martineau' 1st comment:
class A:
a=2
class B(A):
def __init__(self,var):
self.var = var
b = B(42)
b.a
Out[26]: 2
b.var
Out[27]: 42
CodePudding user response:
Here is a solution:
class TopLevel(type):
""" TopLevel metaclass defining class properties. """
@property
def depth(cls) -> int:
return cls._depth
class OtherClass:
""" Class that will inherit from 'TopLevel' after it has been defined.
Dummy implementation."""
def __init__(self, var):
self.var = var
# explicitely add property to OtherClass.__dict__
d = dict(OtherClass.__dict__)
d.update({"depth": TopLevel.depth})
OtherClass = TopLevel(OtherClass.__name__,
OtherClass.__bases__,
d)
OtherClass._depth = 3
otherclass = OtherClass(4)
print(otherclass.depth)