Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does unpacking this map object print "must be an iterable, not map"?

What is going on here?

>>> list(map(lambda *x: x, *map(None, 'abc')))
Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    list(map(lambda *x: x, *map(None, 'abc')))
TypeError: type object argument after * must be an iterable, not map

Ignore the senselessness of the code. This is about the error message, "iterable, not map". Maps are iterables, are they not?

And if I only replace None with str, the whole thing works fine:

>>> list(map(lambda *x: x, *map(str, 'abc')))
[('a', 'b', 'c')]

So now Python doesn't have any issue with a map there after all.

This happens in my Python 3.6.1. My Python 3.5.2 instead raises the expected TypeError: 'NoneType' object is not callable. And googling "must be an iterable, not map" finds no results at all. So apparently this is something introduced just recently.

Is this just a Python bug? Or is there some sense to this?

Update: Reported as bug now, as suggested.

like image 477
Stefan Pochmann Avatar asked Jul 28 '17 01:07

Stefan Pochmann


1 Answers

I'd consider this to be a bug. Here's the source that causes this exception:

https://github.com/python/cpython/blob/b1660800f4f519dbfab9e5a4ad3eae1cfabab3ed/Python/ceval.c#L2514-L2523

A disassembly of the python bytecode confirms it is using BUILD_TUPLE_UNPACK_WITH_CALL

The "bug" in the code above is it assumes any TypeError while _PyList_Extending the argument array means it wasn't an iterable, however __iter__ itself could raise a TypeError. It is rethrowing this exception

I'd suggest opening a bug at https://bugs.python.org

like image 175
Anthony Sottile Avatar answered Nov 05 '22 03:11

Anthony Sottile