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

发布于 2024-11-03 04:54:28 字数 2049 浏览 1 评论 0原文

有没有办法在列表理解中使用没有返回值的方法,例如 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]]
>>> 

Is there a way to use methods with no return value such as random.shuffle in a list comprehension?

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

This is the for loop that applies the random.shuffle method to each item of my 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]]

I can use map, which as a side effect shuffles the original list but returns a list of 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]]

as does using the list comprehension with 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]]

Many questions and answers on stack overflow already point out that using map or a lc for the side effect is bad practice. I was wondering if there's any correct way to use a method with no return value in a list comprehension.

Is writing a method to wrap the non-returning method the only way:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

权谋诡计 2024-11-10 04:54:28

无列表推导式旨在与具有返回值的函数一起使用。这就是它们的语义定义的方式

列表推导式提供了简洁的
无需求助即可创建列表的方法
使用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 函数也很好,并且可以用于列表理解。

No - list comprehensions are meant to be use with functions having return values. It's how their semantics are defined:

List comprehensions provide a concise
way to create lists without resorting
to use of map(), filter() and/or
lambda. The resulting list definition
tends often to be clearer than lists
built using those constructs. Each
list comprehension consists of an
expression followed by a for clause,
then zero or more for or if clauses.
The result will be a list resulting
from evaluating the expression in the
context of the for and if clauses
which follow it.

Having read this, it should be clear that "a list comprehension from a function having no return value" is an oxymoron.

Just use a for loop for something "one off":

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

Clean and simple. Your shuffled function is also just fine, and can be used in a list comprehension.

人│生佛魔见 2024-11-10 04:54:28

伊莱说得很对。但我会选择更简洁的东西:

import random

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

[edit]

OTOH,你可以使用random.sample()

from random import sample

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

Eli is quite right. But I'd go for something more concise:

import random

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

[edit]

OTOH you could use random.sample():

from random import sample

xr = xrange(5)
L = [sample(xr, 5) for each in xr]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文