Search code examples
pythonpython-3.xclassstatic-membersmember-variables

How Can We Determine Whether an Attribute belongs to the Instance or to the Class?


Intro

In Python I want to get a list of all attributes of an object which belong to the class and not to the instance (a list of all static attributes).


Some code to test potential solutions with:

class Klass:

    static_var = 'static_var string'

    def __init__(self):
        self.instance_var = 'instance_var string'

    def instance_method(self, *args, **kwargs):
        pass

    @staticmethod
    def static_method(*args, **kwargs):
        # can be passed almost anything and ignores it.
        pass

obj = Klass()

Failed attempts:

At first I tried the following:

def class_attrs_which_are_not_instance_attrs(obj):
    return set(set(type(obj).__dict__) - set(obj.__dict__))

However, obj.__dict__ is empty, so the function is returning only type(obj).__dict__

Some things I noted:

dir(type(obj)) == dir(obj)

type(obj).__dict__dir(type(obj))


Solution

  • Code

    Here is my solution:

    def static_attributes(obj):
        """
        Generator to return a list of names and attributes which are
        class-level variables or static methods
        """
        klass = type(obj)
        for name, attribute in klass.__dict__.items():
            if not name.startswith('__') and \
                    (type(attribute) in {staticmethod, classmethod} or not callable(attribute)):
                yield name, attribute
    
    for name, attribute in static_attributes(obj):
        print(name)
    

    Output

    static_var
    static_method
    

    Discussion

    • This generator function yields a list of name and attributes that are either staticmethod, classmethod, or class-level variables.
    • I also filtered out those names that starts with dunder (such as __doc__)