Você deve implementar o método __eq__
:
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __eq__(self, other):
if not isinstance(other, MyClass):
# don't attempt to compare against unrelated types
return NotImplemented
return self.foo == other.foo and self.bar == other.bar
Agora ele gera:
>>> x == y
True
Observe que a implementação __eq__
tornará automaticamente instâncias da sua classe unhashable, o que significa que elas não podem ser armazenadas em sets e dict. Se você não está modelando um tipo imutável (ou seja, se os atributos foo
e bar
podem alterar o valor durante a vida útil do seu objeto), é recomendável deixar suas instâncias como removíveis.
Se você estiver modelando um tipo imutável, também deverá implementar o gancho do modelo de dados __hash__
:
class MyClass:
...
def __hash__(self):
# necessary for instances to behave sanely in dicts and sets.
return hash((self.foo, self.bar))
Uma solução geral, como a idéia de repetir __dict__
e comparar valores, não é aconselhável - ela nunca pode ser verdadeiramente geral porque __dict__
pode ter tipos incomparáveis ou removíveis de unhas contidos nela.
Nota: esteja ciente de que antes do Python 3, você pode precisar usar em __cmp__
vez de __eq__
. Os usuários do Python 2 também podem querer implementar __ne__
, pois um comportamento padrão sensível à desigualdade (ou seja, inverter o resultado da igualdade) não será criado automaticamente no Python 2.
return NotImplemented
(em vez de aumentarNotImplementedError
). Esse tópico é abordado aqui: stackoverflow.com/questions/878943/…Você substitui os ricos operadores de comparação em seu objeto.
Como isso:
fonte
__eq__()
, mas apenas um de__lt__()
,__le__()
,__gt__()
, ou__ge__()
é necessário, em adição a isso. A partir disso, o Python pode inferir os outros métodos. Vejafunctools
para mais informações.functools
módulo, mas não para comparadores padrão:MyObj1 != Myobj2
só funcionará se o__ne__()
método for implementado.@functools.total_ordering
decorador em sua classe, em seguida, como acima você pode definir apenas__eq__
e um outro eo resto será derivadoImplemente o
__eq__
método em sua classe; algo assim:Editar: se você deseja que seus objetos sejam comparados iguais se e somente se tiverem dicionários de instância iguais:
fonte
self is other
ver se eles são o mesmo objeto.AttributeError
. Você precisa inserir a linhaif hasattr(other, "path") and hasattr(other, "title"):
(como este belo exemplo na documentação do Python).Como resumo:
__eq__
vez de__cmp__
, exceto se você executar o python <= 2.0 (__eq__
foi adicionado no 2.1)__ne__
(deve ser algo comoreturn not self.__eq__(other)
oureturn not self == other
exceto caso muito especial)Se você deseja comparar com o objeto que pode ser Nenhum, você deve implementá-lo. O intérprete não consegue adivinhar ... (veja o exemplo abaixo)
fonte
Dependendo do seu caso específico, você pode fazer:
Veja o dicionário Python a partir dos campos de um objeto
fonte
Com as classes de dados no Python 3.7 (e superior), uma comparação de instâncias de objetos para igualdade é um recurso embutido.
Um backport para Dataclasses está disponível para Python 3.6.
fonte
Ao comparar instâncias de objetos, a
__cmp__
função é chamada.Se o operador == não estiver funcionando para você por padrão, você sempre poderá redefinir a
__cmp__
função para o objeto.Editar:
Como foi apontado, a
__cmp__
função está obsoleta desde o 3.0. Em vez disso, você deve usar os métodos de "comparação rica" .fonte
Eu escrevi isso e coloquei em um
test/utils
módulo no meu projeto. Nos casos em que não é uma classe, basta planejar o ditado, isso atravessará os dois objetos e garantiráÉ grande ... não é sexy ... mas oh boi funciona!
Você pode limpá-lo um pouco removendo o
_assert
e usando apenas o ol 'simples,assert
mas a mensagem que você recebe quando falha é muito inútil.fonte
Você deve implementar o método
__eq__
:fonte
Abaixo funciona (no meu teste limitado), fazendo uma comparação profunda entre duas hierarquias de objetos. Em lida com vários casos, incluindo os casos em que os próprios objetos ou seus atributos são dicionários.
Este é um código muito complicado, portanto, adicione os casos que possam não funcionar nos comentários.
fonte
fonte
Se você está lidando com uma ou mais classes que não podem ser alteradas internamente, existem maneiras simples e genéricas de fazer isso que também não dependem de uma biblioteca específica do diff:
Método mais fácil e inseguro para objetos muito complexos
pickle
é uma biblioteca de serialização muito comum para objetos Python e, portanto, poderá serializar praticamente qualquer coisa. No trecho acima, estou comparando ostr
de serializadoa
com o deb
. Ao contrário do próximo método, este tem a vantagem de também verificar classes personalizadas.O maior problema: devido a métodos específicos de ordenação e [de / en],
pickle
pode não produzir o mesmo resultado para objetos iguais , especialmente ao lidar com objetos mais complexos (por exemplo, listas de instâncias de classes personalizadas aninhadas), como você frequentemente encontrará em algumas bibliotecas de terceiros. Para esses casos, eu recomendaria uma abordagem diferente:Método completo e seguro para qualquer objeto
Você pode escrever uma reflexão recursiva que fornecerá objetos serializáveis e comparar os resultados
Agora, não importa quais são seus objetos, é garantida que a profunda igualdade funcione
O número de comparáveis também não importa
Meu caso de uso para isso foi verificar a profunda igualdade entre um conjunto diversificado de modelos de Machine Learning já treinados nos testes do BDD. Os modelos pertenciam a um conjunto diversificado de bibliotecas de terceiros. Certamente implementar
__eq__
como outras respostas aqui sugerem que não era uma opção para mim.Cobrindo todas as bases
Você pode estar em um cenário em que uma ou mais das classes personalizadas que estão sendo comparadas não possuem uma
__dict__
implementação . Isso não é comum, por qualquer meio, mas é o caso de um subtipo dentro classificador aleatória Floresta do sklearn:<type 'sklearn.tree._tree.Tree'>
. Trate essas situações caso a caso - por exemplo , especificamente , decidi substituir o conteúdo do tipo afetado pelo conteúdo de um método que me fornece informações representativas sobre a instância (nesse caso, o__getstate__
método). Para isso, a penúltima linha da listabase_typed
tornou-seEdit: por uma questão de organização, substituí as duas últimas linhas
base_typed
porreturn dict_from(obj)
e implementei uma reflexão realmente genérica para acomodar bibliotecas mais obscuras (estou olhando para você, Doc2Vec)Lembre-se de que nenhum dos métodos acima se aplica
True
a objetos diferentes com os mesmos pares de chave-valor, mas com diferentes ordens de chave / valor, como emMas se você quiser, poderá usar o
sorted
método interno do Python de qualquer maneira.fonte
Se você deseja obter uma comparação atributo por atributo e ver se e onde ela falha, você pode usar a seguinte compreensão da lista:
A vantagem extra aqui é que você pode espremer uma linha e entrar na janela "Avaliar expressão" ao depurar no PyCharm.
fonte
Eu tentei o exemplo inicial (veja 7 acima) e ele não funcionou no ipython. Observe que cmp (obj1, obj2) retorna um "1" quando implementado usando duas instâncias de objeto idênticas. Estranhamente, quando modifico um dos valores de atributo e recomparei, usando cmp (obj1, obj2) o objeto continua retornando um "1". (suspiro...)
Ok, então o que você precisa fazer é iterar dois objetos e comparar cada atributo usando o sinal ==.
fonte
A instância de uma classe quando comparada com == é diferente de. A melhor maneira é atribuir a função cmp à sua classe, que fará as coisas.
Se você quiser fazer uma comparação pelo conteúdo, basta usar cmp (obj1, obj2)
No seu caso, cmp (doc1, doc2) retornará -1 se o conteúdo for o mesmo.
fonte