파이썬 set ([])은 두 객체가 같은지 어떻게 확인합니까? 이것을 사용자 정의하기 위해 객체는 어떤 메소드를 정의해야합니까?


85

파이썬에서 '컨테이너'객체 또는 클래스를 만들어야합니다.이 클래스는 내가 정의한 다른 객체의 기록을 유지합니다. 이 컨테이너의 한 가지 요구 사항은 두 개체가 동일한 것으로 간주되면 하나 (둘 중 하나)가 제거된다는 것입니다. 내 첫 번째 생각은 set([])이 요구 사항을 완료하기 위해 포함 개체로 를 사용하는 것이 었습니다 .

그러나 집합은 두 개의 동일한 개체 인스턴스 중 하나를 제거하지 않습니다. 계정을 만들려면 무엇을 정의해야합니까?

다음은 Python 코드입니다.

class Item(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __repr__(self):
    return "Item(%s, %s)" % (self.foo, self.bar)
  def __eq__(self, other):
    if isinstance(other, Item):
      return ((self.foo == other.foo) and (self.bar == other.bar))
    else:
      return False
  def __ne__(self, other):
    return (not self.__eq__(other))

통역사

>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])

__eq__()의해 x == y호출되는은 세트에 의해 호출되는 메서드가 아님 이 분명합니다 . 무엇이라고하나요? 다른 어떤 방법을 정의해야합니까?

참고 : Items는 변경 가능해야하며 변경 될 수 있으므로 메서드를 제공 할 수 없습니다 __hash__(). 이것이 유일한 방법이라면 불변 Item의 사용을 위해 다시 작성할 것 입니다.


1
이 같은 문제가있었습니다. 코드 내에서 소량의 데이터를 조작한다고 가정합니다. 이것은 아마도 데이터베이스 사용에 적합한 후보가 아닐 것입니다. 나는 집합을 생성하고 C ++로 비교기 함수를 정의 할 수 있었던 것을 기억하고 있으며 Java도 믿고 있지만 파이썬에서 사전 객체로 이것을 할 수있는 것처럼 보이지는 않습니다. 누군가 이것을 할 수있는 파이썬으로 "set"라이브러리를 작성한 것 같지만, 나는 하나를 모릅니다.
Chris Dutrow 2013 년

답변:


32

__hash__()방법 을 제공해야 할 것 같습니다 . 그러나 Item.


3
< docs.python.org/reference/… > 여기 두 번째 단락에서는 __hash__()불변 객체에 대해서만 정의되어야한다고 지적 합니다.
Ada

1
@Nathanael : 객체를 변경해야하는 경우 frozenset () 및 set ()과 같이 객체의 변경 불가능한 사본을 만들 수 있습니다.
Lie Ryan

2
@Nathanael-어떻게 전화 __eq__하시겠습니까? 그 (1,2) 속성을 비교합니까? 그런 다음 __hash__메서드 에서도 (1,2)의 해시를 반환해야 합니다.
음미로

또는 foo와 bar는 모두 불변이므로 __hash __ ()는 foo와 bar의 해시 합계를 반환 할 수 있습니까? 아니요 ... 합계가 너무 불안정합니다 ... foo가 1이고 bar 2이면 bar는 1이고 foo는 2입니다. 이는 잘못된 것입니다. 이 목적을 위해 어떤 수학 함수를 사용할 수 있습니까? 모듈로 또는 나눗셈이 작동해야합니다.
Ada

1
Nathanael : hash내장 : hash((self.foo, self.bar)). 이것은 당신의 필요에 적합한 튜플의 해시를 사용합니다. ( 비교 용으로 __eq__도 작성할 수 있습니다 tuple.)
Pi Delport

76

예, __hash__()이미 제공 한 -method와 비교 연산자 가 필요합니다 .

class Item(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    def __repr__(self):
        return "Item(%s, %s)" % (self.foo, self.bar)
    def __eq__(self, other):
        if isinstance(other, Item):
            return ((self.foo == other.foo) and (self.bar == other.bar))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    def __hash__(self):
        return hash(self.__repr__())

3
파이썬 3에서, 당신은 필요하지 않습니다 __ne__, 심지어 2.x에서, 당신은 정의하지 말아야 __ne__의 관점에서 __eq__. 참조 : stackoverflow.com/a/30676267/5337834
John Strood 2018 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.