Home > Enterprise >  A class property does not make it to the instance of the inheriting class?
A class property does not make it to the instance of the inheriting class?

Time:12-06

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)
  • Related