Inspect python class attributes

Below is the hard way. Here’s the easy way. Don’t know why it didn’t occur to me sooner.

import inspect

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    return [item
            for item in inspect.getmembers(cls)
            if item[0] not in boring]

Here’s a start

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    attrs = {}
    bases = reversed(inspect.getmro(cls))   
    for base in bases:
        if hasattr(base, '__dict__'):
            attrs.update(base.__dict__)
        elif hasattr(base, '__slots__'):
            if hasattr(base, base.__slots__[0]): 
                # We're dealing with a non-string sequence or one char string
                for item in base.__slots__:
                    attrs[item] = getattr(base, item)
            else: 
                # We're dealing with a single identifier as a string
                attrs[base.__slots__] = getattr(base, base.__slots__)
    for key in boring:
        del attrs['key']  # we can be sure it will be present so no need to guard this
    return attrs

This should be fairly robust. Essentially, it works by getting the attributes that are on a default subclass of object to ignore. It then gets the mro of the class that’s passed to it and traverses it in reverse order so that subclass keys can overwrite superclass keys. It returns a dictionary of key-value pairs. If you want a list of key, value tuples like in inspect.getmembers then just return either attrs.items() or list(attrs.items()) in Python 3.

If you don’t actually want to traverse the mro and just want attributes defined directly on the subclass then it’s easier:

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    if hasattr(cls, '__dict__'):
        attrs = cls.__dict__.copy()
    elif hasattr(cls, '__slots__'):
        if hasattr(base, base.__slots__[0]): 
            # We're dealing with a non-string sequence or one char string
            for item in base.__slots__:
                attrs[item] = getattr(base, item)
            else: 
                # We're dealing with a single identifier as a string
                attrs[base.__slots__] = getattr(base, base.__slots__)
    for key in boring:
        del attrs['key']  # we can be sure it will be present so no need to guard this
    return attrs

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)