Python: цикл for для назначения индекса - PullRequest
4 голосов
/ 14 октября 2011

Работая с удивительной книгой Тоби Сегарана «Программирование коллективного интеллекта», я столкнулся с некоторыми приемами в назначениях индексов, с которыми я не совсем знаком.

Возьмем, к примеру,

createkey='_'.join(sorted([str(wi) for wi in wordids]))

или:

normalizedscores = dict([(u,float(l)/maxscore) for (u,l) in linkscores.items()])

Все вложенные кортежи в индексах меня немного смущают.Что на самом деле присваивается этим переменным?Я предположил, очевидно, что .join выходит в виде строки, но как насчет последнего?Если бы кто-то мог объяснить механику этих петель, я был бы очень благодарен.Я предполагаю, что это довольно распространенные приемы, но, будучи новичком в Python, полагаю, что позор на мгновение.Спасибо!

Ответы [ 6 ]

15 голосов
/ 14 октября 2011
[str(wi) for wi in wordids]

является списком .

a = [str(wi) for wi in wordids]

совпадает с

a = []
for wi in wordids:
    a.append(str(wi))

Итак

createkey='_'.join(sorted([str(wi) for wi in wordids]))

создает список строк из каждого элемента в wordids, затем сортирует этот список и объединяет его в большую строку, используя _ в качестве разделителя.

Как правильно заметил agf, вы можететакже используйте выражение генератора, которое выглядит так же, как понимание списка, но с скобками вместо скобок.Это позволяет избежать построения списка, если он вам больше не нужен (за исключением итерации по нему).И если у вас уже есть скобки, как в этом случае с sorted(...), вы можете просто снять скобки.

Однако в этом особом случае вы не получите выигрыша в производительности (на самом деле это будет примерно на 10% медленнее; я рассчитал это время), потому что sorted() в любом случае потребуется создать список,но выглядит немного лучше:

createkey='_'.join(sorted(str(wi) for wi in wordids))

normalizedscores = dict([(u,float(l)/maxscore) for (u,l) in linkscores.items()])

перебирает элементы словаря linkscores, где каждый элемент является парой ключ / значение.Он создает список ключевых / l/maxscore кортежей, а затем превращает этот список обратно в словарь.

Однако, начиная с Python 2.7, вы также можете использовать dict comphingings :

normalizedscores = {u:float(l)/maxscore for (u,l) in linkscores.items()}

Вот некоторые временные данные:

Python 3.2.2

>>> import timeit
>>> timeit.timeit(stmt="a = '_'.join(sorted([str(x) for x in n]))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
61.37724242267409
>>> timeit.timeit(stmt="a = '_'.join(sorted(str(x) for x in n))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
66.01814811313774

Python 2.7.2

>>> import timeit
>>> timeit.timeit(stmt="a = '_'.join(sorted([str(x) for x in n]))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
58.01728623923137
>>> timeit.timeit(stmt="a = '_'.join(sorted(str(x) for x in n))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
60.58927580777687
3 голосов
/ 14 октября 2011

Давайте возьмем первый:

  1. str(wi) for wi in wordids берет каждый элемент в wordids и преобразует его в строку.
  2. sorted(...) сортирует их (лексикографически).
  3. '_'.join(...) объединяет отсортированные идентификаторы слов в одну строку с подчеркиванием между записями.

Теперь второй:

normalizedscores = dict([(u,float(1)/maxscore) for (u,l) in linkscores.items()])
  1. linkscores - это словарь (или словарь-подобный объект).
  2. for (u,l) in linkscores.items() перебирает все записи в словаре, для каждой записи присваивая ключ и значение u и l.
  3. (u,float(1)/maxscore) - это кортеж, первый элемент которого - u, а второй - 1/maxscore (для меня это выглядит как опечатка: float(l)/maxscore будет иметь больше смысла - примечание строчная буква el вместо одного).
  4. dict(...) создает словарь из списка кортежей, в котором первый элемент каждого кортежа берется в качестве ключа, а второй - в качестве значения.

Короче говоря, он создает копию словаря, сохраняя ключи и деля каждое значение на maxscore.

1 голос
/ 14 октября 2011

Странно выглядящий бизнес, заключающийся в скобках [], называется пониманием списка, и это в основном очень лаконичный способ построения списка.myList = [str(wi) for wi in wordids] эквивалентно:

myList = []

for wi in wordids:
  myList.append(str(wi))

sorted(), затем сортирует этот список, а join() дает строку с этими элементами списка, разделенными подчеркиванием, например: item1_item2_item3_....

Второе присваивание более сложное / краткое, но вот что происходит:

  • linkscores выглядит как словарь, а метод items() возвращает список из (key, value) кортежей изтолковый словарь.Так что for (u,l) in linkscores.items() зацикливается на этом списке.
  • Для каждого из этих кортежей мы создаем новый кортеж, содержащий (u, float(l)/maxscore), и добавляем его в список.Таким образом, этот шаг в основном меняет ваш список (item, value) на список (item, normalized value) кортежей.
  • Функция dict() превращает это обратно в словарь.

Общий результат состоит в том, чтобы взять все значения в dict и нормализовать их.Там может быть более простой / более многословный способ сделать это, но этот способ имеет то преимущество, что выглядит круто.Я предпочитаю не делать сумасшедшие вещи со списком, потому что это ухудшает читабельность, так что совсем не расстраивайся, если тебе самому не хочется писать такие вещи!

1 голос
/ 14 октября 2011

Вот пример первого ... пример

>>> wordids = [1,2,4,3,10,7]
>>> createkey='_'.join(sorted([str(wi) for wi in wordids]))
>>> print createkey
1_10_2_3_4_7

Он выполняет итерацию по списку с помощью цикла for, сортировку списка, затем объединяет все отсортированные значения встрока, разделяющая значения с помощью '_'

1 голос
/ 14 октября 2011
[(u,float(1)/maxscore) for (u,l) in linkscores.items()]

Это создает список путем итерации по кортежам в linkscores.items() и вычисления (u, float(l)/maxscore) для каждого кортежа.

dict([this list])

создает dict с записями из результата понимания списка - (u, float(l)/maxscore) для каждого элемента в linkscores.

В качестве другого примера создания диктата из списка кортежей:

>>> l = [(1,2), (3,4), (5,6)]
>>> d = dict(l)
>>> d
{1: 2, 3: 4, 5: 6}
1 голос
/ 14 октября 2011

Последний эквивалентен:

normalizedscores = {}
for u, l in linkscores.items():
    normalizedscores[u] = float(l) / maxscore
...