from collections import defaultdict def find_missing_attrs_per_item(module, *attr_names, prefilter=lambda k, v: True): """ returns dict with per prefiltered item name in the module, which of attr_names are missing (only if there are any) """ missing = defaultdict(list) for name, item in vars(module).items(): if prefilter(name, item): for attr_name in attr_names: if not hasattr(item, attr_name): missing[name].append(attr_name) return missing def find_items_per_missing_attr(module, *attr_names, prefilter=lambda k, v: True): """ returns dict with per attr name which (filtered) items (names) in the module, do not have this attribute (inverse of find_missing_attrs_per_item) """ missing = defaultdict(list) for name, item in vars(module).items(): if prefilter(name, item): for attr_name in attr_names: if not hasattr(item, attr_name): missing[attr_name].append(name) return missing if __name__ == '__main__': import inspect import typing, collections def _filter(name, item): """ exclude funtions, modules, uppercase and staring with underscore """ return not (inspect.isfunction(item) or inspect.ismodule(item) or name == name.upper() or name.startswith('_')) missing_per_item = find_missing_attrs_per_item(typing, *dir(type), prefilter=_filter) print("\n---") for name, miss in sorted(missing_per_item.items()): print(name, miss) missing_per_attr = find_items_per_missing_attr(typing, *dir(type), prefilter=_filter) print("\n---") for name, miss in missing_per_attr.items(): print(name, sorted(miss, key=lambda m: len(type(m).__mro__)))