Есть ли простой способ сравнить два объекта класса для всех элементов, которые не являются ни одним из них?

Я хочу сравнить два экземпляра одного и того же класса, но только те элементы, для которых оба не являются 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__ каждого класса для перебора атрибутов, но мне было интересно, может ли это быть пониманием списка.

Разве вы не можете просто сравнить dict напрямую, вместо того, чтобы перебирать их самостоятельно? т.е. def Bolt.__eq__(self, other): return self.__dict__ == other.__dict__ Реализация dict.__eq__ уже обрабатывает то, что вы хотите сделать.

Samwise 14.05.2022 16:05

Спасибо, но, учитывая, что словари не будут полностью равными (только их части) - как это будет работать?

tricha122 14.05.2022 20:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
49
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я бы просто упростил:

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

Спасибо, я думаю, что это лучший подход!

tricha122 14.05.2022 20:05

У меня нет точно требований для равенства, но я думаю, что 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

Другие вопросы по теме