Изящные способы поддерживать эквивалентность (“равенство”) в классах Python

On:

  • Ubuntu 14.04
  • mysql Ver 14.14 Распространение 5.7.16 для Linux (x86_64) с использованием обложек EditLine

Do:

$ sudo nano /etc/mysql/conf.d/mysql.cnf

Скопировать и вставить:

[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

В нижней части файла

$ sudo service mysql restart
383
задан 4 revs, 2 users 100% 11 July 2009 в 13:34
поделиться

6 ответов

Необходимо быть осторожными с наследованием:

>>> class Foo:
    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

>>> class Bar(Foo):pass

>>> b = Bar()
>>> f = Foo()
>>> f == b
True
>>> b == f
False

Проверка вводит более строго, как это:

def __eq__(self, other):
    if type(other) is type(self):
        return self.__dict__ == other.__dict__
    return False

Помимо этого, Ваш подход будет хорошо работать, это - то, для чего специальные методы там.

195
ответ дан Algorias 22 November 2019 в 23:53
поделиться

Путем Вы описываете, способ, которым я всегда делал его. Так как это полностью универсально, можно всегда выламывать ту функциональность в смесительный класс и наследовать ее в классах, где Вы хотите ту функциональность.

class CommonEqualityMixin(object):

    def __eq__(self, other):
        return (isinstance(other, self.__class__)
            and self.__dict__ == other.__dict__)

    def __ne__(self, other):
        return not self.__eq__(other)

class Foo(CommonEqualityMixin):

    def __init__(self, item):
        self.item = item
158
ответ дан 3 revs, 2 users 94% 22 November 2019 в 23:53
поделиться

Вы не должны переопределять и __eq__, и __ne__ можно переопределить [только 112], но это сделает импликацию на результате ==! ==, <> и так далее.

is тесты для объектных идентификационных данных. Это означает is, b будет True в случае, когда a и b оба будут содержать ссылку на тот же объект. В Python Вы всегда держите ссылку на объект в переменной не фактический объект, поэтому по существу для b, чтобы быть верными, что объекты в них должны быть расположены в той же ячейке памяти. Как и самое главное почему Вы пошли бы о переопределении этого поведения?

Редактирование: Я не знал __cmp__, был удален из python 3, так избегайте его.

8
ответ дан 4 revs, 2 users 89% 22 November 2019 в 23:53
поделиться

Я думаю, что два условия, которые Вы ищете, равенство (==) и , идентификационные данные . Например:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> a == b
True       <-- a and b have values which are equal
>>> a is b
False      <-- a and b are not the same list object
2
ответ дан too much php 22 November 2019 в 23:53
поделиться

Тест, протестирует на идентификационные данные с помощью встроенного 'идентификатора ()' функция, которая по существу возвращает адрес памяти объекта и поэтому не является сверхзагружаемой.

Однако в случае тестирования равенства класса Вы, вероятно, хотите быть строгими о своих тестах и только сравнить атрибуты данных в Вашем классе:

import types

class ComparesNicely(object):

    def __eq__(self, other):
        for key, value in self.__dict__.iteritems():
            if (isinstance(value, types.FunctionType) or 
                    key.startswith("__")):
                continue

            if key not in other.__dict__:
                return False

            if other.__dict__[key] != value:
                return False

         return True

Этот код только сравнит не функциональные элементы данных Вашего класса, а также пропуска чего-либо частного, которое обычно является, что Вы хотите. В случае Простых Объектов Python у меня есть базовый класс, который реализует __ init __, __ str __, __ repr __ и __ eq __, таким образом, мои объекты POPO не несут нагрузку всего этого дополнительного (и в большинстве случаев идентичный) логика.

1
ответ дан 2 revs 22 November 2019 в 23:53
поделиться

Это включает комментарии к ответу Algorias и сравнивает объекты единственным атрибутом, потому что я не забочусь о целом dict. Я знаю other.id, существует, потому что я установил его в конструкторе.

def __eq__(self, other):
    if other is self:
        return True

    if type(other) is not type(self):
        # delegate to superclass
        return NotImplemented

    return other.id == self.id
0
ответ дан 22 November 2019 в 23:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: