Чтение последовательности целых чисел с использованием map в python - PullRequest
0 голосов
/ 09 февраля 2012

Может кто-нибудь объяснить, как работает следующий код на python? Этот код читает последовательность целых чисел, которые расположены в виде трех кортежей.

inverted_list = map(lambda i: (int(numbers[2 + 3*i]),
                           float(numbers[3 + 3*i]),
                           float(numbers[4 + 3*i]))
                    ,range(0, (len(numbers) - 2)/3))

Как именно работает карта и лямбда? Действительно ли здесь нужна лямбда?

Спасибо.

Ответы [ 4 ]

1 голос
/ 09 февраля 2012

У вас уже есть ответы, которые объясняют более приятные или более современные способы выразить это, но я хотел бы продемонстрировать, что именно делают лямбда и карта с точки зрения более основных функций.Прежде всего, вот ваш пример:

inverted_list = map(lambda i: (int(numbers[2 + 3*i]),
                               float(numbers[3 + 3*i]),
                               float(numbers[4 + 3*i]))
                    ,range(0, (len(numbers) - 2)/3))

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

func = lambda i:(int(numbers[2 + 3*i]),
                 float(numbers[3 + 3*i]),
                 float(numbers[4 + 3*i]))
sequence = range(0, (len(numbers) - 2)/3)
inverted_list = map(func, sequence)

lambda - это просто способ выразить простую функцию внутри выражения.Мы можем заменить его обычной функцией без изменения эффекта:

def func(i):
    return (int(numbers[2 + 3*i]),
            float(numbers[3 + 3*i]),
            float(numbers[4 + 3*i]))
sequence = range(0, (len(numbers) - 2)/3)
inverted_list = map(func, sequence)

map - это то, что называется «функцией более высокого порядка», функцией, которая принимает в качестве аргумента другую функцию.map будет перебирать каждый элемент в sequence, вызывать func с этим элементом в качестве аргумента, принимать все, что возвращает функция, и добавлять его в новый список. *

Если вы хотите сделатьТо же самое без функций более высокого порядка или выражений-генераторов, вы можете написать это длинным путем:

def func(i):
    return (int(numbers[2 + 3*i]),
            float(numbers[3 + 3*i]),
            float(numbers[4 + 3*i]))
sequence = range(0, (len(numbers) - 2)/3)
inverted_list = []
for item in sequence:
    inverted_list.append(func(item))

Преимущество лямбды заключается в том, что вы можете выразить в одном выражении то, что в противном случае потребовало бы введения временных переменных и, возможнообъявив функцию каким-то образом до точки, которую вы хотите использовать.Преимущество map заключается в том, что вы можете написать в одном выражении что-то, что в противном случае потребовало бы временных переменных и цикла.

(*) В Python 3 map фактически возвращает итератор, а не список.

1 голос
/ 09 февраля 2012

Нет, лямбда здесь на самом деле не требуется, это также можно записать как:

inverted_list = [(int(numbers[2 + 3*i]),
                  float(numbers[3 + 3*i]),
                  float(numbers[4 + 3*i])) for i in range(0, (len(numbers) - 2)/3]

Я не буду вдаваться в математический бит индексаторов, поскольку сегодня я только на своей первой чашке кофе, но то, что делает map, - это применяет функцию к последовательности, генерируя новую последовательность с результат функции для каждого элемента. lambda - это функция, в данном случае создающая кортеж из ваших чисел. Последовательность - это выражение range, которое дает вам список i значений, которые вы можете использовать в выражениях индексации (например, 3 + 3*i).

Версия вашего фрагмента кода @gnibbler и я показываем вам современный python. Это не было, скажем, в Python 1.5 - поэтому мы использовали map, reduce, zip и другие «функциональные» операции высокого порядка. Мне лично они очень нравятся, но я думаю, что они обречены на замену для большинства задач - списки в этих случаях более выразительны!

1 голос
/ 09 февраля 2012

Создает список

(numbers[2],numbers[3], numbers[4], numbers[2 + 3],numbers[3 + 3], numbers[4 + 3], ...., numbers[2 + 3*((len(numbers) -2)/3)],numbers[3 +  3*((len(numbers) -2)/3)], numbers[4 + 3*((len(numbers) -2)/3)]

, отображающий диапазон:

range(0, (len(numbers) - 2)/3)

для кортежей с лямбдой.

Один из способов - использовать понимание списка и выполнить итерациюдиапазон, начинающийся с 2 с шагом 3 размера:

[(int(numbers[i]), float(numbers[i + 1]), float(numbers[i + 2])) for i in range(2,len(numbers), 3)]
1 голос
/ 09 февраля 2012

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

inverted_list = [((int(numbers[2 + 3*i]), float(numbers[3 + 3*i]), 
                float(numbers[4 + 3*i])) for i in range(0, (len(numbers) - 2)/3)]

Бьет меня, почему вы умножили бы i на 3 везде,

inverted_list = [((int(numbers[i]), float(numbers[1+i]), 
                float(numbers[2+i])) for i in range(2, len(numbers), 3)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...