Почему моя попытка распаковать карту приводит к тому, что объект `TypeError: 'int' не повторяется` - PullRequest
0 голосов
/ 09 ноября 2019

Я знаю, что TypeError: 'int' object is not iterable происходит, когда мы пытаемся перебрать что-то, что не повторяется. Например,

for x in 4:
    pass

m = map(str, 99)

В моем случае я создаю карту, и, хотя есть проблема, она не терпит неудачу позже. Что-то вроде следующей строки выполняется просто отлично

m = map(foo, [1, 2, 3])

Проблема с моей функцией foo. Позже, когда я пытаюсь распаковать итератор карты, например, написав list(m), foo поднимает TypeError, я просто не могу понять, почему.

import itertools    

def contains_iter(cont):
    """
    returns true if container is an iterator
                 or
                 if container is not an iterator
                 but container contains an iterator
                 or
                 if container is not an iterator
                 but container contains a container
                 which contains an iterator.
                 etc...
    """
    range_type = type(range(1))
    if hasattr(cont, "__next__") or isinstance(cont, range_type):
        return True
    try:
        for elem in cont:
            if elem == cont:
                # string "a" in "a"
                break
            if contains_iter(elem):
                return True
        r = False
    except TypeError:
        # object is not iterable
        r = False
    finally:
        pass
    return r

def deiter(it):
    status = contains_iter(it)
    if status:
        assert(hasattr(it, "__iter__"))
        mahp = map(deiter, it)
        tup = tuple(mahp)
        return tup
    return it


def print_io(inny):
    def outty(*args):
        args = deiter(args)
        try:
            output = inny(*args)
        except BaseException as exc:
            output = str(type(exc)) + str(exc)
        output = deiter(output)
        call_sig = "flatten" + str(args)
        output = "OUTPUT:  " + str(output)
        print(40*"#", call_sig, output, 40*"#", sep="\n")
        return
    return outty

class FlatClass:
    def __call__(self, *args):
        try:
            if len(args) <= 1:
                try:
                    r = iter(args[0])
                except BaseException:
                    r = args[0]
                    # if len(args) == 0
                    # `args[0]` raises
                    # exception
            else:
                args = map(self, args)
                r = itertools.chain(*args)
        except IndexError:
            r = tuple() # empty tuple
        finally:
            pass
        return r

flatten = print_io(FlatClass())

flatten(1, [2])

1 Ответ

3 голосов
/ 09 ноября 2019

У вас есть itertools.chain вызов, который пытается связать вещи, которые не являются итеративными:

else:
    args = map(self, args)
    r = itertools.chain(*args)

Некоторые из этих аргументов являются целыми числами. Это не обнаружено при создании цепного итератора, только когда вы в конце концов попытаетесь выполнить итерацию по нему.

Не зная, какова была цель этого кода, мы не можем сказать, как это исправить. Есть много других частей этого кода, которые являются подозрительными (диапазоны не являются итераторами), бесцельными (finally: pass) или излишне запутанными (range_type = type(range(1)) просто устанавливает range_type = range), и есть почти наверняка больше ошибок, ноименно это вызывает непосредственную проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...