将没有返回值的方法应用于列表的每个元素
问题内容:
有没有办法在列表推导中使用没有返回值的方法(例如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]]
>>>
问题答案:
否-列表推导旨在与具有返回值的函数一起使用。这是它们的语义定义的方式:
列表理解为创建列表提供了一种简洁的方法,而无需使用map(),filter()和/或lambda。所得的列表定义往往比使用这些构造构建的列表更清晰。每个列表理解都包含一个表达式,后跟一个for子句,然后是零个或多个for或if子句。结果将是一个列表,该列表是通过在紧随其后的for和if子句的上下文中评估表达式而得出的。
读完此书后,应该很清楚,“对没有返回值的函数的列表理解”是矛盾的。
只需使用一个for
循环就可以实现“一次性”:
import random
L = []
for x in range(5):
l = range(5)
random.shuffle(l)
L.append(l)
干净简单。您的shuffled
函数也很好, 可以 在列表理解中使用。