Разница между контуром "for" и картой

Из названия да, есть разница. Теперь применим к моему сценарию: рассмотрим класс Dummy:

class Dummy:
    def __init__(self):
        self.attached = []

    def attach_item(self, item):
        self.attached.append(item)

Если я использую это:

D = Dummy()
items = [1, 2, 3, 4]
for item in items:
    D.attach_item(item)

Я действительно получаю D.attached = [1, 2, 3, 4]. Но если я сопоставляю функцию attach_item с items, D.attached остается пустым.

map(D.attach_item, items)

Что он делает?

Ответ 1

Очень интересный вопрос, который имеет интересный ответ.

Функция map возвращает объект Map, который является итерируемым. map выполняет свой расчет лениво, поэтому функция не будет вызвана, если вы не повторите этот объект.

Поэтому, если вы это сделаете:

x = map(D.attach_item, items)
for i in x:
    continue

Ожидаемый результат появится.

Ответ 2

map создает только итератор. Вы должны перебирать его, чтобы добавить элементы в D.attached. Как это:

D = Dummy()
items = [1, 2, 3, 4]
list(map(D.attach_item, items))

Да, не делай этого в своем коде :) Но этот пример полезен только для понимания.

Ответ 3

Цитирование документации

Верните итератор, который применяет функцию к каждому элементу итерации, давая результаты.

что означает, что вам необходимо собрать итератор, например

list(map(D.attach_item, items))

> [None, None, None, None]

Хммм, странно. Почему нет, нет,...

Да, вы можете преобразовать любой цикл в оператор карты, но это не всегда полезно. Карта берет параметр и делает что-то с ним (в большинстве случаев) возвращает его без побочных эффектов! Вот пример:

def add(a):
    return a + 3
list(map(add, items))

> [4, 5, 6, 7]

Истинная сила приходит, когда вы объединяете ее с другими функциями, такими как filter

def add(a):
    return a + 3
def odd(a):
    return a % 2 == 1
list(map(add, filter(odd, items)))

> [4, 6]