Почему карта past.builtins ведет себя неправильно? - PullRequest
2 голосов
/ 12 марта 2020

Так как в map есть некоторая разница в поведении (особенно с тремя аргументами между Python 2 и Python - Python 2 против Python 3 - Разница в поведении карты с тремя аргументами? ), я пытался быть "безопасным", используя from past.builtins import map, чтобы моя функциональность не изменилась. Но это не так?

Вот код Python 2:

map(lambda x: [x], [1, 2])

, который дает:

[[1], [2]]

Вот это * Код 1038 * 3, который я ожидаю, будет вести себя так же, но не будет:

from past.builtins import map
map(lambda x: [x], [1, 2])

дает:

[1, 2]

Удивительно, но новый map работает как ожидалось:

from builtins import map  # Not needed if you didn't evaluate the above code.
list(map(lambda x: [x], [1, 2]))

Есть ли причина, по которой past.builtins map ведет себя так? Это ошибка?


Похоже, есть некоторые проблемы с получением Python 2 map поведения с использованием модуля past.builtins, как упомянуто в исходном коде комментарии .

1 Ответ

2 голосов
/ 12 марта 2020

Это ошибка в их реализации map. Вот их код для этого:

def oldmap(func, *iterables):
    """
    map(function, sequence[, sequence, ...]) -> list
    Return a list of the results of applying the function to the
    items of the argument sequence(s).  If more than one sequence is
    given, the function is called with an argument list consisting of
    the corresponding item of each sequence, substituting None for
    missing values when not all sequences have the same length.  If
    the function is None, return a list of the items of the sequence
    (or a list of tuples if more than one sequence).
    Test cases:
    >>> oldmap(None, 'hello world')
    ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
    >>> oldmap(None, range(4))
    [0, 1, 2, 3]
    More test cases are in past.tests.test_builtins.
    """
    zipped = itertools.zip_longest(*iterables)
    l = list(zipped)
    if len(l) == 0:
        return []
    if func is None:
        result = l
    else:
        result = list(starmap(func, l))

    # Inspect to see whether it's a simple sequence of tuples
    try:
        if max([len(item) for item in result]) == 1:
            return list(chain.from_iterable(result))
        # return list(flatmap(func, result))
    except TypeError as e:
        # Simple objects like ints have no len()
        pass
    return result

Ошибка, где говорится:

# Inspect to see whether it's a simple sequence of tuples

В их реализации, если вызываемый объект возвращает список объектов с len из затем они «распаковываются» и возвращается плоский список. Хотя я не уверен, откуда это взялось, поскольку, насколько я знаю, Python 2 не делал этого даже для кортежей:

# Python 2
print(map(lambda x: (x,), [1, 2]))
# [(1,), (2,)]

Кажется, что открыт сообщите об этом в хранилище кода библиотеки, если вы хотите следовать этому.

...