Применение метода без возвращаемого значения к каждому элементу списка - PullRequest
7 голосов
/ 24 апреля 2011

Есть ли способ использовать методы без возвращаемого значения, такие как random.shuffle в понимании списка?

>>> import pprint
>>> import random
>>> 
>>> L = [ random.shuffle(range(5)) for x in range(5)]
>>> 
>>> print L
[None, None, None, None, None]

Это цикл for, который применяет метод random.shuffle к каждому элементу моегоlist:

>>> L = [ range(5) for x in range(5) ]
>>> pprint.pprint(L)
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4]]
>>> for element in L:
...     random.shuffle(element)
... 
>>> pprint.pprint(L)
[[2, 0, 3, 1, 4],
 [2, 0, 1, 4, 3],
 [4, 1, 3, 0, 2],
 [1, 2, 4, 3, 0],
 [1, 3, 0, 2, 4]]

Я могу использовать карту, которая в качестве побочного эффекта перетасовывает исходный список, но возвращает список None

>>> L = [ range(5) for x in range(5) ]
>>> pprint.pprint(L)
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4]]
>>> map(random.shuffle, L)
[None, None, None, None, None]
>>> pprint.pprint(L)
[[3, 0, 4, 1, 2],
 [2, 3, 0, 1, 4],
 [2, 3, 1, 4, 0],
 [4, 2, 0, 3, 1],
 [1, 3, 0, 2, 4]]

, как и при использовании понимания списка с shuffle:

>>> L = [ range(5) for x in range(5) ]
>>> pprint.pprint(L)
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4]]
>>> L1 = [ random.shuffle(x) for x in L ]
>>> pprint.pprint(L1)
[None, None, None, None, None]
>>> pprint.pprint(L)
[[1, 4, 0, 2, 3],
 [0, 4, 1, 3, 2],
 [2, 3, 4, 0, 1],
 [4, 1, 0, 2, 3],
 [2, 0, 4, 3, 1]]

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

Пишет метод, чтобы обернуть невозвратный метод единственным способом:

>>> def shuffled(L):
...     ret_val = L[:]
...     random.shuffle(ret_val)
...     return ret_val
... 
>>> L = [ shuffled(range(5)) for x in range(5)]
>>> pprint.pprint(L)
[[2, 1, 0, 4, 3],
 [4, 0, 3, 1, 2],
 [4, 2, 3, 0, 1],
 [1, 0, 4, 2, 3],
 [2, 4, 3, 0, 1]]
>>> 

Ответы [ 2 ]

11 голосов
/ 24 апреля 2011

Нет - список пониманий предназначен для использования с функциями, имеющими возвращаемые значения. Так определяется их семантика :

Список представлений дает краткое способ создания списков без обращения использовать map (), filter () и / или лямбда. Результирующее определение списка часто бывает понятнее списков построен с использованием этих конструкций. каждый Понимание списка состоит из выражение, сопровождаемое предложением for, тогда ноль или более для или если условия. Результатом будет список в результате от оценки выражения в контекст предложений for и if которые следуют за этим.

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

Просто используйте цикл for для чего-то «одноразового»:

import random
L = []
for x in range(5):
  l = range(5)
  random.shuffle(l)
  L.append(l)

Чисто и просто. Ваша shuffled функция также хороша, и может использоваться для понимания списка.

8 голосов
/ 24 апреля 2011

Илай совершенно прав.Но я бы пошел на что-то более краткое:

import random

L = [range(5) for each in xrange(5)]
for each in L:
    random.shuffle(each)

[править]

OTOH вы можете использовать random.sample():

from random import sample

xr = xrange(5)
L = [sample(xr, 5) for each in xr]
...