I want to check if two classes (not instances of these classes) are identical in the sense that they have identical class attributes.
The trivial approach is to override __eq__
and __hash__
1, but this will only allow comparing instances of the classes.
I wonder if this is even possible as it seems like python uses id
to check for equality between the classes which can not be overridden.
The desired outcome is something like this:
class FOO:
SOME_ATTR=3
class BAR1:
SOME_ATTR=3
class BAR2:
SOME_ATTR=1
set(FOO, BAR1, BAR2) == SET(FOO, BAR2)
CodePudding user response:
To get a set of attributes of a Python class, for example
class MyClass:
my_attr: 2
you can use
set(x for x in MyClass.__dict__.keys() if not x.startswith('__'))
then compare the sets of the classes
CodePudding user response:
If you want to know if the attributes of classes are the same, you can use the inspect.getmembers()
function and filter for attributes without dunders. Note that attributes of classes are mutable!
import inspect
class FOO:
SOME_ATTR=3
def my_func():
pass
class BAR1:
SOME_ATTR=3
class BAR2:
SOME_ATTR=1
def compare_classes(class1: type, class2: type) -> bool:
attr_class1 = inspect.getmembers(class1, lambda a:not(inspect.isroutine(a)))
attr_class2 = inspect.getmembers(class2, lambda a:not(inspect.isroutine(a)))
set_class1 = set([a for a in attr_class1 if not(a[0].startswith('__') and a[0].endswith('__'))])
set_class2 = set([a for a in attr_class2 if not(a[0].startswith('__') and a[0].endswith('__'))])
return set_class1 == set_class2
print(compare_classes(FOO, BAR1))
print(compare_classes(BAR1, BAR2))
Outcome:
True
False