2012-02-09 4 views
0

Может ли кто-нибудь объяснить, как работает следующий код python? Этот код читает ряд целых чисел, которые расположены в виде 3-х кортежей.Чтение последовательности целых чисел с использованием карты в 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)) 

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

Спасибо.

ответ

1

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

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, и я показываю вас, это modern python. Это было не вокруг, скажем, python 1.5 - поэтому мы использовали map, reduce, zip и другие «функциональные» операции высокого порядка. Мне лично они очень нравятся, но я полагаю, что обречен на замену для большинства задач. В таких случаях, как этот, более выразительные списки более выразительны!

1

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

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)] 
+0

Потому что первые 2 числа не являются частью последовательности. Я думаю, что он эффективно запускает цикл, начиная с третьего элемента серии. Я был просто смущен тем, что карта/лямбда выполняет любую другую операцию здесь. –

1

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

(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

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

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)) 

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

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

Смежные вопросы