将没有返回值的方法应用于列表的每个元素

时间:2011-04-23 20:44:46

标签: python list-comprehension

有没有办法在列表推导中使用没有返回值的方法,例如random.shuffle?

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

这是将random.shuffle方法应用于列表中每个项目的for循环:

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

我可以使用map,这是一个副作用混洗原始列表但返回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 个答案:

答案 0 :(得分:11)

否 - 列表推导意味着与具有返回值的函数一起使用。这就是他们的语义are defined

  

列表理解提供了简洁   无需求助即可创建列表的方法   使用map(),filter()和/或   拉姆达。结果列表定义   往往比列表更清晰   使用这些结构构建。每   列表理解包括一个   表达式后跟一个for子句,   然后零或更多for或if子句。   结果将是一个列表   从评估中的表达式   for和if子句的上下文   跟着它。

读过这篇文章后,应该清楚“从一个没有返回值的函数中得到列表”是一种矛盾。

只需使用for循环“一次性”:

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

干净简单。您的shuffled功能也很好,可以用于列表理解。

答案 1 :(得分:8)

<\ n> Eli是对的。但我会更简洁一些:

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]