3

我有一个cheese对象列表。Cheese有一种方法可以用 db 和诸如此类的东西做很多事情,称为out_of_stock().

所以:

[cheese.out_of_stock() for cheese in cheeses]

我觉得很草率。就像我正在为一堆副作用(清零库存)做某事(创建一个列表)。

我是不是很傻?这对方法来说是主观的吗?

4

8 回答 8

10

列表推导用于创建列表。这不是你在这里做的,所以我会避免它。

于 2012-08-02T04:44:26.607 回答
6

就个人而言,我会做

for cheese in cheeses:
    cheese.out_of_stock()

这对我来说感觉更明确。这是另一行,但我怀疑另一个阅读该代码的程序员会很好地理解它,而列表理解版本可能会有点混乱。此外,我可以想象其他人可能会稍后出现(不知道out_of_stock不会返回值)并稍后尝试使用该列表。

不过,我想这并没有什么问题。归根结底,这取决于谁将在以后阅读该代码(您自己或其他人)以及他们是否会知道发生了什么。

编辑:另外,您正在使用从 Haskell 中获取的可爱的函数式编程结构来做令人讨厌的有状态的事情......

于 2012-08-02T04:40:25.907 回答
4

从语义上讲,如果 cheese.out_of_stock 返回一个布尔值,那就没问题了。但是,如果 cheese.out_of_stock 不返回值,则不太推荐这样做,那么它将非常混乱且无法维护。

import this

了解更多信息

于 2012-08-02T04:43:40.523 回答
2

列表推导通常用于过滤(或稍后使用推导结果的类似操作),但不用于替换对迭代数据调用方法的循环。所以这行得通,但它锁得很丑。

于 2012-08-02T04:40:13.277 回答
2

如果您正在使用 this 的返回值做某事,那么cheese.out_of_stock()这完全是 Pythonic。如果您要丢弃列表理解的结果,那是不好的风格。

创建列表是浪费时间和内存,只需使用彼得答案for中的两行循环

于 2012-08-02T05:26:00.070 回答
1

答案完全取决于您是否想要这份清单。列表推导通常可以很好地替代这样的循环:

stock = []
for cheese in cheeses:
   stock.append(cheese.out_of_stock())

但很少有这样的循环:

for cheese in cheeses:
    cheese.out_of_stock()

当人们阅读列表理解时,他们通常不会期望它有副作用——除了像缓存这样不会影响程序含义的东西,当然还有构建列表。当然,对于程序的正确性来说,它的任何副作用都不是必需的——这也意味着如果你使用没有命令-查询分离的 API,那么对于第一种类型的循环来说,它们是值得避免的——也就是说,即使你确实想要列表,如果.out_of_stock() 具有您所依赖的副作用,则应考虑使用循环而不是理解。

于 2012-08-02T06:00:34.997 回答
1

太丑了,别做

有一种非常相似的方法,它并不难看。它需要一个像这样的预定义函数:

def consume(iter):
    for i in iter:
        pass

现在您可以编写如下代码:

consume(cheese.out_of_stock() for cheese in cheeses)

所以真的,这只是 Peters 的建议,包装在一个用生成器表达式调用的函数中。虽然比列表理解要好得多,但它仍然不是很漂亮。最好(最明确)直接使用 for 循环。

于 2012-08-02T06:36:37.073 回答
0
for cheese in cheeses: cheese.out_of_stock()

仍然是一个衬里,避免了创建不必要列表的副作用。

于 2012-08-02T04:42:57.060 回答