summaryrefslogtreecommitdiffstats
path: root/Lib/sets.py
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-03-02 00:19:49 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-03-02 00:19:49 (GMT)
commit44f14b039949005ecc93fd8294933c84fab6f374 (patch)
treee68c8735baa42a015f34cd37c2d3c89020f8ee97 /Lib/sets.py
parent3ba491e6b1747707374e56fd9f0fb958b2aafcd5 (diff)
downloadcpython-44f14b039949005ecc93fd8294933c84fab6f374.zip
cpython-44f14b039949005ecc93fd8294933c84fab6f374.tar.gz
cpython-44f14b039949005ecc93fd8294933c84fab6f374.tar.bz2
SF bug 693121: Set == non-Set is a TypeError.
Allow mixed-type __eq__ and __ne__ for Set objects. This is messier than I'd like because Set *also* implements __cmp__. I know of one glitch now: cmp(s, t) returns 0 now when s and t are both Sets and s == t, despite that Set.__cmp__ unconditionally raises TypeError (and by intent). The rub is that __eq__ gets tried first, and the x.__eq__(y) True result convinces Python that cmp(x, y) is 0 without even calling Set.__cmp__.
Diffstat (limited to 'Lib/sets.py')
-rw-r--r--Lib/sets.py32
1 files changed, 26 insertions, 6 deletions
diff --git a/Lib/sets.py b/Lib/sets.py
index 0824fb1..e6a509f 100644
--- a/Lib/sets.py
+++ b/Lib/sets.py
@@ -102,20 +102,40 @@ class BaseSet(object):
"""
return self._data.iterkeys()
- # Three-way comparison is not supported
+ # Three-way comparison is not supported. However, because __eq__ is
+ # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and
+ # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this
+ # case).
def __cmp__(self, other):
raise TypeError, "can't compare sets using cmp()"
- # Equality comparisons using the underlying dicts
+ # Equality comparisons using the underlying dicts. Mixed-type comparisons
+ # are allowed here, where Set == z for non-Set z always returns False,
+ # and Set != z always True. This allows expressions like "x in y" to
+ # give the expected result when y is a sequence of mixed types, not
+ # raising a pointless TypeError just because y contains a Set, or x is
+ # a Set and y contain's a non-set ("in" invokes only __eq__).
+ # Subtle: it would be nicer if __eq__ and __ne__ could return
+ # NotImplemented instead of True or False. Then the other comparand
+ # would get a chance to determine the result, and if the other comparand
+ # also returned NotImplemented then it would fall back to object address
+ # comparison (which would always return False for __eq__ and always
+ # True for __ne__). However, that doesn't work, because this type
+ # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented,
+ # Python tries __cmp__ next, and the __cmp__ here then raises TypeError.
def __eq__(self, other):
- self._binary_sanity_check(other)
- return self._data == other._data
+ if isinstance(other, BaseSet):
+ return self._data == other._data
+ else:
+ return False
def __ne__(self, other):
- self._binary_sanity_check(other)
- return self._data != other._data
+ if isinstance(other, BaseSet):
+ return self._data != other._data
+ else:
+ return True
# Copying operations