Home > front end >  Python | Get all static-class variables of all sublcasses in parent class
Python | Get all static-class variables of all sublcasses in parent class

Time:05-02

I want to get all class variable names of all sub-classes in my parent class (in python). While I managed to do that I'm not certain if there is a cleaner way to achieve that.

Pseudo code to explain the problem :

class Parent:
    all_names = []
    var_1 = 1
    
    def __init__(self):
       print(self.all_names) 

class ChildA(Parent):
    var_2 = 2

class ChildB(ChildA):
    var_3 = 3
  
p = Parent()
ca = ChildA()
cb = ChildB()

>>> ["var_1"]
>>> ["var_1","var_2"]
>>> ["var_1","var_2","var_3"]

So what I am currently doing is that I use the __new__ function to set those values recursively :


class Parent(object):
    test_1 = 1

    signals = []

    def __new__(cls, *args, **kwargs):
        # create obj ref
        _obj = super().__new__(cls, *args, **kwargs)
 
        signals = []

        # walk every base and add values
        def __walk(base):
            for key, value in vars(base).items():
                if <condition>
                    signals.append(value.__name__)

            for base in base.__bases__:
                __walk(base)

        __walk(cls)

        signals.reverse() # to reorder the list

        _obj.signals = signals

        return _obj

For more context: I am trying to develop a Signal-System but to check whether an instance has a Signal I somehow need to add them to the Root-Parent-Class. Yes I could Make all Subclasses inherit from a helper class but I don't want to do that and instead have it all bundled in as few classes as possible.

Also if there are any bugs/risks with my implementation please let me know I just recently discovered __new__.

(Python 3.x)

CodePudding user response:

You could walk up the method resolution order and check for any keys in each class's __dict__ that do not appear in object.__dict__ and are not callable or private keys.

class Parent:
    var_p = 1
    def __init__(self):
        self.blah = 0
        class_vars = []
        for cls in self.__class__.mro()[:-1]:
            class_vars.extend([
                k for k, v in cls.__dict__.items()
                if k not in object.__dict__ and not k.startswith('_')
                and not callable(v)
            ])
        print(class_vars)

    def test(self):
        return True

class ChildA(Parent):
    var_a = 2


class ChildB(ChildA):
    var_b = 3

p = Parent()
ca = ChildA()
cb = ChildB()

# prints:
['var_p']
['var_a', 'var_p']
['var_b', 'var_a', 'var_p']
  • Related