title: Conversion to set of custom collections class returns empty set in Python
body: <p>I've recently written my own OrderedSet implementation since I had problems with the publicly available ordered/sorted set implementations. The class uses a dict proxy object in the background and mostly forwards operations. I implemented all (in my opinion) relevant methods, incl. <code>__iter__</code>, and calls like <code>list(myset)</code> work as expected.</p>
  <p>However, the call <code>set(myset)</code> <em>always</em> returns empty sets.</p>
  <p>Here's the full code of OrderedSet:</p>
  <pre class="lang-py prettyprint-override"><code>from typing import TypeVar, Generic, Optional, Iterable, Set, AbstractSet, Union, Iterator, Any, Dict
  
  T = TypeVar(&quot;T&quot;)
  S = TypeVar(&quot;S&quot;)
  
  
  class OrderedSet(Generic[T], Set[T]):
      def __init__(self, base: Optional[Union[Dict[T, None], Iterable[T]]] = None):
          super().__init__()
  
          self.the_dict: Dict[T, None]
          if not base:
              self.the_dict = {}
          elif isinstance(base, dict):
              self.the_dict = base
          else:
              self.the_dict = dict.fromkeys(base)
  
      def __eq__(self, o: object) -&gt; bool:
          return isinstance(o, OrderedSet) and list(self.the_dict) == list(o.the_dict)
  
      def __ne__(self, o: object) -&gt; bool:
          return not self.__eq__(o)
  
      def __str__(self) -&gt; str:
          return &quot;{&quot; + &quot;, &quot;.join(list(map(str, self.the_dict))) + &quot;}&quot;
  
      def __repr__(self) -&gt; str:
          return f&quot;OrderedSet({repr(self.the_dict)})&quot;
  
      def add(self, element: T) -&gt; None:
          self.the_dict = {**self.the_dict, **{element: None}}
  
      def clear(self) -&gt; None:
          self.the_dict.clear()
  
      def copy(self) -&gt; 'OrderedSet[T]':
          return OrderedSet(self.the_dict.copy())
  
      def difference(self, s: Iterable[Any]) -&gt; 'OrderedSet[T]':
          return OrderedSet({e: None for e in self.the_dict if e not in s})
  
      def difference_update(self, s: Iterable[Any]) -&gt; None:
          self.the_dict = {e: None for e in self.the_dict if e not in s}
  
      def discard(self, element: T) -&gt; None:
          del self.the_dict[element]
  
      def intersection(self, s: Iterable[Any]) -&gt; 'OrderedSet[T]':
          return OrderedSet({e: None for e in self.the_dict if e in s})
  
      def intersection_update(self, s: Iterable[Any]) -&gt; None:
          self.the_dict = {e: None for e in self.the_dict if e in s}
  
      def isdisjoint(self, s: Iterable[Any]) -&gt; bool:
          return self.the_dict.keys().isdisjoint(s)
  
      def issubset(self, s: Iterable[Any]) -&gt; bool:
          return set(iter(self)).issubset(iter(s))
  
      def issuperset(self, s: Iterable[Any]) -&gt; bool:
          return set(iter(self)).issuperset(iter(s))
  
      def pop(self) -&gt; T:
          items = list(self.the_dict)
          result = items.pop()
          self.the_dict = dict.fromkeys(items)
          return result
  
      def remove(self, element: T) -&gt; None:
          del self.the_dict[element]
  
      def symmetric_difference(self, s: Iterable[T]) -&gt; 'OrderedSet[T]':
          return OrderedSet(
              dict.fromkeys([e for e in self.the_dict if e not in s] +
                            [e for e in s if e not in self.the_dict]))
  
      def symmetric_difference_update(self, s: Iterable[T]) -&gt; None:
          self.the_dict = self.symmetric_difference(s).the_dict
  
      def union(self, s: Iterable[T]) -&gt; 'OrderedSet[T]':
          return OrderedSet({**self.the_dict, **dict.fromkeys(s)})
  
      def update(self, s: Iterable[T]) -&gt; None:
          self.the_dict = self.union(s).the_dict
  
      def __len__(self) -&gt; int:
          return len(self.the_dict)
  
      def __contains__(self, o: object) -&gt; bool:
          return o in self.the_dict
  
      def __iter__(self) -&gt; Iterator[T]:
          return iter(self.the_dict)
  
      def __and__(self, s: AbstractSet[object]) -&gt; 'OrderedSet[T]':
          return self.intersection(s)
  
      def __iand__(self, s: AbstractSet[object]) -&gt; 'OrderedSet[T]':
          result = self.intersection(s)
          self.the_dict = result.the_dict
          return result
  
      def __or__(self, s: AbstractSet[S]) -&gt; 'OrderedSet[Union[T, S]]':
          return self.union(s)
  
      def __ior__(self, s: AbstractSet[S]) -&gt; 'OrderedSet[Union[T, S]]':
          result = self.union(s)
          self.the_dict = result.the_dict
          return result
  
      def __sub__(self, s: AbstractSet[Optional[T]]) -&gt; 'OrderedSet[T]':
          return self.difference(s)
  
      def __isub__(self, s: AbstractSet[Optional[T]]) -&gt; 'OrderedSet[T]':
          result = self.difference(s)
          self.the_dict = result.the_dict
          return result
  
      def __xor__(self, s: AbstractSet[S]) -&gt; 'OrderedSet[Union[T, S]]':
          return self.symmetric_difference(s)
  
      def __ixor__(self, s: AbstractSet[S]) -&gt; 'OrderedSet[Union[T, S]]':
          result = self.symmetric_difference(s)
          self.the_dict = result.the_dict
          return result
  
      def __le__(self, s: AbstractSet[object]) -&gt; bool:
          return self.issubset(s)
  
      def __lt__(self, s: AbstractSet[object]) -&gt; bool:
          return self.issubset(s) and len(self) &lt; len(s)
  
      def __ge__(self, s: AbstractSet[object]) -&gt; bool:
          return set(iter(self)) &gt;= set(iter(s))
  
      def __gt__(self, s: AbstractSet[object]) -&gt; bool:
          return set(iter(self)) &gt; set(iter(s))
  </code></pre>
  <p>And here some example calls:</p>
  <pre class="lang-py prettyprint-override"><code>&gt;&gt;&gt; from orderedset import OrderedSet
  &gt;&gt;&gt; s = OrderedSet([3, 1, 2])
  &gt;&gt;&gt; s
  OrderedSet({3: None, 1: None, 2: None})
  &gt;&gt;&gt; list(s)
  [3, 1, 2]
  &gt;&gt;&gt; set(s)
  set()
  </code></pre>
  <p>Does anybody have an idea what's going on here? The <code>set()</code> function seems to be implemented in lengthy C code, which I don't understand well enough to deduce anything. It seems, though, that <code>__iter__</code> is called for conversion to <code>list</code>, but not to <code>set</code>...</p>
  <p>Any ideas?</p>
  <p>Thanks a lot!</p>