什么时候放弃列表理解和python方法?

什么时候放弃列表理解和python方法?,python,list-comprehension,pylint,code-complete,Python,List Comprehension,Pylint,Code Complete,我创建了一行,用以下方式将对象附加到列表中 >>> foo = list() >>> def sum(a, b): ... c = a+b; return c ... >>> bar_list = [9,8,7,6,5,4,3,2,1,0] >>> [foo.append(sum(i,x)) for i, x in enumerate(bar_list)] [None, None, None, None, None

我创建了一行,用以下方式将对象附加到列表中

>>> foo = list()
>>> def sum(a, b):
...      c = a+b; return c
...
>>> bar_list = [9,8,7,6,5,4,3,2,1,0]
>>> [foo.append(sum(i,x)) for i, x in enumerate(bar_list)]
[None, None, None, None, None, None, None, None, None, None]
>>> foo
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>>>
线路

[foo.append(sum(i,x)) for i, x in enumerate(bar_list)]
将给出一个pylint W1060表达式,但由于我已经在使用foo列表来附加值,所以我不需要将列表理解行分配给某些内容

我的问题更多的是编程正确性的问题

我是否应该放弃列表理解,只使用一个简单的表达式

>>> for i, x in enumerate(bar_list):
...      foo.append(sum(i,x))
还是有一种正确的方法可以同时使用列表理解和赋值

回答

谢谢@user2387370、@kindall和@Martijn Pieters。对于其余的注释,我使用append,因为我没有使用list(),我没有使用I+x,因为这只是一个简化的示例

我留下的内容如下:

histogramsCtr = hist_impl.HistogramsContainer()
for index, tupl in enumerate(local_ranges_per_histogram_list):
    histogramsCtr.append(doSubHistogramData(index, tupl))
return histogramsCtr

我认为人们通常不赞成仅仅为了副作用而使用列表理解,所以我认为在这种情况下使用for循环更好


但是在任何情况下,你不能只做
foo=[sum(i,x)for i,x in enumerate(bar_list)]

你应该明确地放弃列表。结束

  • 您正在混淆任何阅读您的代码的人。您正在建立副作用列表
  • 您正在为构建一个再次丢弃的列表而支付CPU周期和内存
在您的简化案例中,您忽略了您可以直接使用列表理解的事实:

[sum(i,x) for i, x in enumerate(bar_list)]

是的,这是一种糟糕的风格。列表理解就是建立一个列表。您正在构建一个包含
None
s的列表,然后将其丢弃。您实际期望的结果是这一努力的副作用

为什么不首先使用列表理解定义
foo

foo = [sum(i,x) for i, x in enumerate(bar_list)]
如果它不是列表,而是其他容器类,正如您在另一个答案的注释中所提到的,那么编写该类以在其构造函数中接受iterable(或者,如果不是您的代码,则将其子类化以接受iterable),然后向其传递一个生成器表达式:

foo = MyContainer(sum(i, x) for i, x in enumerate(bar_list))
如果
foo
已具有某些值,并且您希望附加新项目:

foo.extend(sum(i,x) for i, x in enumerate(bar_list))
如果您确实想使用
append()
,并且出于某种原因不想使用
for
循环,那么您可以使用此构造;生成器表达式至少可以避免在不需要的列表上浪费内存和CPU周期:

any(foo.append(sum(i, x)) for i, x in enumerate(bar_list))
但这远不如常规的
for
循环清晰,而且还有一些额外的工作要做:
any
正在测试每次迭代的
foo.append()
的返回值。您可以编写一个函数来使用迭代器并消除该检查;最快的方法是使用零长度的集合。deque:

from collections import deque
do = deque([], maxlen=0).extend

do(foo.append(sum(i, x)) for i, x in enumerate(bar_list))

这实际上是相当可读的,但我相信它实际上并不比
any()
快,并且需要额外的导入。然而,如果这是一个问题的话,
do()
any()
for
循环快一点。

我意识到这只是一个例子,但为什么要追加呢?为什么不干脆
foo=[sum(i,x)…]
sum(i,x)
不起作用。你是说
i+x
?如果你真的想要一行,你可以在一行上放一个
for
循环。但不推荐。我不能,因为在我的程序中,foo是一个容器对象,append方法会做一些其他事情。然后,要么只使用for循环,要么,如果容器对象属于您定义的类,可能会将
\uuuu init\uuuuuuu
更改为使用*args,这样您就可以执行
foo=MyContainerFoo(枚举(bar\u列表)中I,x的总和(I,x))
不需要使用
*args
。生成器表达式是一个参数。很抱歉,我的意思是我更愿意将其定义为可以初始化为
MyClass(1,2,3,4,5)
(使用*args)或
MyClass(*(范围(1,6)中的I代表I))
,而不是
MyClass([1,2,3,4,5])
MyClass(范围(1,6)中的I代表I)
,但这就是我。