Я хочу сравнить два экземпляра одного и того же класса, но только те элементы, для которых оба не являются None
.
например,
У меня будет класс Bolt
, и один экземпляр будет иметь:
bolt1.locx = 1.0
bolt1.locy = 2.0
bolt1.locz = 3.0
bolt1.rpid = 1234
bolt1.nsid = [1,2,3,4]
bolt2.locx = 1.0
bolt2.locy = 2.0
bolt2.locz = 3.0
bolt2.rpid = None
bolt2.nsid = None
В этом случае я хочу сравнить эти классы как истинные.
Я знаю, что могу использовать __dict__
каждого класса для перебора атрибутов, но мне было интересно, может ли это быть пониманием списка.
Спасибо, но, учитывая, что словари не будут полностью равными (только их части) - как это будет работать?
Я бы просто упростил:
class Bolt:
# ...
def __eq__(self, other):
if [self.locx, self.locy, self.locz] != [other.locx, other.locy, other.locz]:
return False
if self.rpid is not None && other.rpid is not None && self.rpid != other.rpid:
return False
if self.nsid is not None && other.nsid is not None && self.nsid != other.nsid:
return False
return True
Спасибо, я думаю, что это лучший подход!
У меня нет точно требований для равенства, но я думаю, что
attrgetter
от operator
может пригодиться для сравнения экземпляров в цикле. Вот пример использования:
from operator import attrgetter
attrs = ('locx', 'locx', 'locz', 'rpid', 'nsid')
checks = []
for attr in attrs:
attr1 = attrgetter(attr)(bolt1)
attr2 = attrgetter(attr)(bolt2)
if attr1 is None and attr2 is None:
continue
checks.append(attr1 == attr2)
print(all(checks))
Вот более общий способ сделать это, который не требует жесткого кодирования сравнений атрибутов.
class Bolt:
def __eq__(self, other):
# check if the objects have a different set of attributes
if self.__dict__.keys() != other.__dict__.keys():
return False
for attr, self_attr in self.__dict__.items():
other_attr = getattr(other, attr)
if (self_attr is None) or (other_attr is None):
continue
elif self_attr != other_attr:
return False
return True
bolt1 = Bolt()
bolt2 = Bolt()
bolt1.locx = 1.0
bolt1.locy = 2.0
bolt1.locz = 3.0
bolt1.rpid = 1234
bolt1.nsid = [1,2,3,4]
bolt2.locx = 1.0
bolt2.locy = 2.0
bolt2.locz = 3.0
bolt2.rpid = None
bolt2.nsid = None
Выход:
>>> bolt1.__dict__
{'locx': 1.0, 'locy': 2.0, 'locz': 3.0, 'rpid': 1234, 'nsid': [1, 2, 3, 4]}
>>> bolt2.__dict__
{'locx': 1.0, 'locy': 2.0, 'locz': 3.0, 'rpid': None, 'nsid': None}
>>> bolt1 == bolt2
True
>>> bolt2.rpid = 1
>>> bolt2.__dict__
{'locx': 1.0, 'locy': 2.0, 'locz': 3.0, 'rpid': 1, 'nsid': None}
>>> bolt1 == bolt2
False # different 'rpid' attribute values
>>> bolt2.rpid = None
>>> bolt2.extra_attr = 2
>>> bolt2.__dict__
{'locx': 1.0, 'locy': 2.0, 'locz': 3.0, 'rpid': None, 'nsid': None, 'extra_attr': 2}
>>> bolt1 == bolt2
False # different set of attributes
Разве вы не можете просто сравнить
dict
напрямую, вместо того, чтобы перебирать их самостоятельно? т.е.def Bolt.__eq__(self, other): return self.__dict__ == other.__dict__
Реализацияdict.__eq__
уже обрабатывает то, что вы хотите сделать.