IT story

파이썬에서 객체 인스턴스가 속성에 의해 동일한 지 비교

hot-time 2020. 4. 28. 08:23
반응형

파이썬에서 객체 인스턴스가 속성에 의해 동일한 지 비교


나는 수업이 MyClass두 멤버 변수가 포함되어, foobar:

class MyClass:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

나는에 대해 동일한 값을 가지고 각각의이 클래스의 두 인스턴스가 foo와를 bar:

x = MyClass('foo', 'bar')
y = MyClass('foo', 'bar')

그러나 동등성을 비교하면 Python은 False다음을 반환합니다 .

>>> x == y
False

파이썬 이이 두 객체를 동등하게 생각하게하려면 어떻게해야합니까?


메소드를 구현해야합니다 __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

이제 출력합니다 :

>>> x == y
True

구현 __eq__하면 클래스의 인스턴스를 해시 할 수 없게되므로 세트와 딕트에 저장할 수 없습니다. 당신은 불변의 유형을 모델링하지 않는 경우 (즉, 속성 경우 foobar개체의 수명 내에서 값을 변경할 수 있음), 다음은 그냥 unhashable로 인스턴스를두고하는 것이 좋습니다.

불변 유형을 모델링하는 경우 datamodel 후크도 구현해야합니다 __hash__.

class MyClass:
    ...

    def __hash__(self):
        # necessary for instances to behave sanely in dicts and sets.
        return hash((self.foo, self.bar))

__dict__을 반복 하고 비교 하는 아이디어와 같은 일반적인 솔루션 은 권장되지 않습니다. __dict__비교할 수 없거나 해시 할 수없는 유형이 포함되어 있기 때문에 실제로는 결코 일반적인 방법이 될 수 없습니다 .

N.B.: be aware that before Python 3, you may need to use __cmp__ instead of __eq__. Python 2 users may also want to implement __ne__, since a sensible default behaviour for inequality (i.e. inverting the equality result) will not be automatically created in Python 2.


You override the rich comparison operators in your object.

class MyClass:
 def __lt__(self, other):
      # return comparison
 def __le__(self, other):
      # return comparison
 def __eq__(self, other):
      # return comparison
 def __ne__(self, other):
      # return comparison
 def __gt__(self, other):
      # return comparison
 def __ge__(self, other):
      # return comparison

Like this:

    def __eq__(self, other):
        return self._id == other._id

Implement the __eq__ method in your class; something like this:

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

Edit: if you want your objects to compare equal if and only if they have equal instance dictionaries:

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

As a summary :

  1. It's advised to implement __eq__ rather than __cmp__, except if you run python <= 2.0 (__eq__ has been added in 2.1)
  2. Don't forget to also implement __ne__ (should be something like return not self.__eq__(other) or return not self == other except very special case)
  3. Don`t forget that the operator must be implemented in each custom class you want to compare (see example below).
  4. If you want to compare with object that can be None, you must implement it. The interpreter cannot guess it ... (see example below)

    class B(object):
      def __init__(self):
        self.name = "toto"
      def __eq__(self, other):
        if other is None:
          return False
        return self.name == other.name
    
    class A(object):
      def __init__(self):
        self.toto = "titi"
        self.b_inst = B()
      def __eq__(self, other):
        if other is None:
          return False
        return (self.toto, self.b_inst) == (other.toto, other.b_inst)
    

When comparing instances of objects, the __cmp__ function is called.

If the == operator is not working for you by default, you can always redefine the __cmp__ function for the object.

Edit:

As has been pointed out, the __cmp__ function is deprecated since 3.0. Instead you should use the “rich comparison” methods.


Depending on your specific case, you could do:

>>> vars(x) == vars(y)
True

See Python dictionary from an object's fields


If you want to get an attribute-by-attribute comparison, and see if and where it fails, you can use the following list comprehension:

[i for i,j in 
 zip([getattr(obj_1, attr) for attr in dir(obj_1)],
     [getattr(obj_2, attr) for attr in dir(obj_2)]) 
 if not i==j]

The extra advantage here is that you can squeeze it one line and enter in the "Evaluate Expression" window when debugging in PyCharm.


I tried the initial example (see 7 above) and it did not work in ipython. Note that cmp(obj1,obj2) returns a "1" when implemented using two identical object instances. Oddly enough when I modify one of the attribute values and recompare, using cmp(obj1,obj2) the object continues to return a "1". (sigh...)

Ok, so what you need to do is iterate two objects and compare each attribute using the == sign.


Instance of a class when compared with == comes to non-equal. The best way is to ass the cmp function to your class which will do the stuff.

If you want to do comparison by the content you can simply use cmp(obj1,obj2)

In your case cmp(doc1,doc2) It will return -1 if the content wise they are same.

참고URL : https://stackoverflow.com/questions/1227121/compare-object-instances-for-equality-by-their-attributes-in-python

반응형