有没有一种方法可以检查python中的两个类是否相同



编辑:给定具有固定属性的N个类,我的目标是找到唯一类的最小集合,它将是所有N个类的超集。

我想检查两个类(而不是这些类的实例(是否相同,因为它们具有相同的类属性。

琐碎的方法是覆盖__eq____hash__1,但这只允许比较类的实例。

我想知道这是否可能,因为python似乎使用id来检查不能重写的类之间的相等性。

想要的结果是这样的:

class FOO:
SOME_ATTR=3
class BAR1:
SOME_ATTR=3
class BAR2:
SOME_ATTR=1
set(FOO, BAR1, BAR2) == set(FOO, BAR2)

如果您想知道类的属性是否相同,可以使用inspect.getmembers()函数并过滤不带Dunder的属性。注意,类的属性是可变的!

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))

结果:

True
False

获取Python类的一组属性,例如

class MyClass:
my_attr: 2

你可以使用

set(x for x in MyClass.__dict__.keys() if not x.startswith('__'))

然后比较类的集合

尝试:

class minSetCls():
def __init__(self, list_of_classes):
self._dctCAttrsCName = {}
self.add(list_of_classes)
def add(self, list_of_classes):
for c in list_of_classes:
attrdict = {}
clasdict = c.__dict__
for key, val in clasdict.items():
if not key.startswith('_') and not callable(val): 
attrdict[key] = val
self._dctCAttrsCName[ tuple(sorted(list(attrdict.items()))) ] = c.__name__
def get(self): 
return sorted(self._dctCAttrsCName.values())
mSCs = minSetCls([BAR1, BAR2, BAR3]) 
print( mSCs.get() )
mSCs.add([BAR4, BAR5]) 
print( mSCs.get() )

上:

class BAR1: # << same as BAR3   ----
SOME_ATTR=3
class BAR1sub1:
SOME_ATTR = 3
class BAR2: # >> UNIQUE         BAR2
SOME_ATTR=2
class BAR3: # >> MASKS BAR1     BAR3
SOME_ATTR=3
class BAR4: # << same as BAR5   ----
SOME_OTHER_ATTR=4
class BAR4sub1:
SOME_ATTR = 4
class BAR5: # >> MASKS BAR4     BAR5
SOME_OTHER_ATTR=4

将提供什么:

['BAR2', 'BAR3']
['BAR2', 'BAR3', 'BAR5']

最新更新