Another attempt at making the set constructor both safe and fast. [SF
bug 628246]
diff --git a/Lib/sets.py b/Lib/sets.py
index 5a66a2e..a05c66f 100644
--- a/Lib/sets.py
+++ b/Lib/sets.py
@@ -319,26 +319,32 @@
data.update(iterable)
return
- # If the mere process of iterating may raise TypeError, materialize
- # the iterable into a tuple first. Then the TypeError will get
- # raised here and propagated back to the caller. Once we get into
- # the loop following, TypeError is assumed to mean that element
- # can't be used as a dict key.
- if type(iterable) not in (list, tuple, dict, file, xrange, str):
- iterable = tuple(iterable)
-
- it = iter(iterable)
value = True
- while True:
- try:
- for element in it:
+
+ if type(iterable) in (list, tuple, xrange):
+ # Optimized: we know that __iter__() and next() can't
+ # raise TypeError, so we can move 'try:' out of the loop.
+ it = iter(iterable)
+ while True:
+ try:
+ for element in it:
+ data[element] = value
+ return
+ except TypeError:
+ transform = getattr(element, "_as_immutable", None)
+ if transform is None:
+ raise # re-raise the TypeError exception we caught
+ data[transform()] = value
+ else:
+ # Safe: only catch TypeError where intended
+ for element in iterable:
+ try:
data[element] = value
- return
- except TypeError:
- transform = getattr(element, "_as_immutable", None)
- if transform is None:
- raise # re-raise the TypeError exception we caught
- data[transform()] = value
+ except TypeError:
+ transform = getattr(element, "_as_immutable", None)
+ if transform is None:
+ raise # re-raise the TypeError exception we caught
+ data[transform()] = value
class ImmutableSet(BaseSet):