title: TypeError: function() argument after * must be a sequence, not generator
body: <p>While trying to write a tiny, obfuscated type checker, an unacceptable code pattern was discovered. However, it inconsistently fails to work properly. This is the code that was initally written to test it with.</p>
  
  <pre><code>def statictypes(a):
      def b(a, b, c):
          if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c)))
          return c
      return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*(b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)))))
  
  @statictypes
  def isallinstance(iterable: object, class_or_type_or_tuple: (type, tuple)) -&gt; bool:
      """isallinstance(iterable, class_or_type_or_tuple) -&gt; bool
  
      Return whether all items in an iterable are instances of a class or of a
      subclass thereof. With a type as second argument, return whether that is
      all items' type. The form using a tuple, isallinstance(x, (A, B, ...)),
      is a shortcut for any(isallinstance(x, y) for y in (A, B, ...)).
      """
      return all(isinstance(item, class_or_type_or_tuple) for item in iterable)
  </code></pre>
  
  <p>The following shows a conversation with Python's interpreter and highlights the error that comes up. A <code>TypeError</code> is generated, but not the one that was expected. While generators were fine, now they fail.</p>
  
  <pre><code>&gt;&gt;&gt; isallinstance(range(1000000), int)
  True
  &gt;&gt;&gt; isallinstance(range(1000000), (int, float))
  True
  &gt;&gt;&gt; isallinstance(range(1000000), [int, float])
  Traceback (most recent call last):
    File "&lt;pyshell#26&gt;", line 1, in &lt;module&gt;
      isallinstance(range(1000000), [int, float])
    File "C:\Users\schappell\Downloads\test.py", line 5, in &lt;lambda&gt;
      return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*(b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)))))
  TypeError: isallinstance() argument after * must be a sequence, not generator
  </code></pre>
  
  <p>The <code>statictypes</code> function can be rewritten, and the <code>isallinstance</code> function redefined and wrapped. The simplest solution is to rewrite  the generatior in <code>statictypes</code> to be a list comprehension.</p>
  
  <pre><code>def statictypes(a):
      def b(a, b, c):
          if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c)))
          return c
      return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)])))
  </code></pre>
  
  <p>After that, the <code>isallinstance</code> will starting working as expected once it is recreated from scratch. The <code>TypeError</code> stating what was wrong with the second argument is properly generated as was desired.</p>
  
  <pre><code>&gt;&gt;&gt; isallinstance(range(1000000), int)
  True
  &gt;&gt;&gt; isallinstance(range(1000000), (int, float))
  True
  &gt;&gt;&gt; isallinstance(range(1000000), [int, float])
  Traceback (most recent call last):
    File "&lt;pyshell#29&gt;", line 1, in &lt;module&gt;
      isallinstance(range(1000000), [int, float])
    File "C:\Users\schappell\Downloads\test.py", line 5, in &lt;lambda&gt;
      return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)])))
    File "C:\Users\schappell\Downloads\test.py", line 5, in &lt;listcomp&gt;
      return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)])))
    File "C:\Users\schappell\Downloads\test.py", line 3, in b
      if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c)))
  TypeError: class_or_type_or_tuple should be (&lt;class 'type'&gt;, &lt;class 'tuple'&gt;), not &lt;class 'list'&gt;
  </code></pre>
  
  <p><strong>Questions:</strong></p>
  
  <ol>
  <li>Why does the first function with the generator somtimes work and other times fail?</li>
  <li>Why is a generator not considered a sequence (since it generates a sequence)?</li>
  <li>Why is a sequence needed when a generator obviously works some of the time?</li>
  </ol>