我有一个cheese
对象列表。Cheese
有一种方法可以用 db 和诸如此类的东西做很多事情,称为out_of_stock()
.
所以:
[cheese.out_of_stock() for cheese in cheeses]
我觉得很草率。就像我正在为一堆副作用(清零库存)做某事(创建一个列表)。
我是不是很傻?这对方法来说是主观的吗?
列表推导用于创建列表。这不是你在这里做的,所以我会避免它。
就个人而言,我会做
for cheese in cheeses:
cheese.out_of_stock()
这对我来说感觉更明确。这是另一行,但我怀疑另一个阅读该代码的程序员会很好地理解它,而列表理解版本可能会有点混乱。此外,我可以想象其他人可能会稍后出现(不知道out_of_stock
不会返回值)并稍后尝试使用该列表。
不过,我想这并没有什么问题。归根结底,这取决于谁将在以后阅读该代码(您自己或其他人)以及他们是否会知道发生了什么。
编辑:另外,您正在使用从 Haskell 中获取的可爱的函数式编程结构来做令人讨厌的有状态的事情......
从语义上讲,如果 cheese.out_of_stock 返回一个布尔值,那就没问题了。但是,如果 cheese.out_of_stock 不返回值,则不太推荐这样做,那么它将非常混乱且无法维护。
import this
了解更多信息
列表推导通常用于过滤(或稍后使用推导结果的类似操作),但不用于替换对迭代数据调用方法的循环。所以这行得通,但它锁得很丑。
如果您正在使用 this 的返回值做某事,那么cheese.out_of_stock()
这完全是 Pythonic。如果您要丢弃列表理解的结果,那是不好的风格。
创建列表是浪费时间和内存,只需使用彼得答案for
中的两行循环
答案完全取决于您是否想要这份清单。列表推导通常可以很好地替代这样的循环:
stock = []
for cheese in cheeses:
stock.append(cheese.out_of_stock())
但很少有这样的循环:
for cheese in cheeses:
cheese.out_of_stock()
当人们阅读列表理解时,他们通常不会期望它有副作用——除了像缓存这样不会影响程序含义的东西,当然还有构建列表。当然,对于程序的正确性来说,它的任何副作用都不是必需的——这也意味着如果你使用没有命令-查询分离的 API,那么对于第一种类型的循环来说,它们是值得避免的——也就是说,即使你确实想要列表,如果.out_of_stock()
还具有您所依赖的副作用,则应考虑使用循环而不是理解。
太丑了,别做
有一种非常相似的方法,它并不难看。它需要一个像这样的预定义函数:
def consume(iter):
for i in iter:
pass
现在您可以编写如下代码:
consume(cheese.out_of_stock() for cheese in cheeses)
所以真的,这只是 Peters 的建议,包装在一个用生成器表达式调用的函数中。虽然比列表理解要好得多,但它仍然不是很漂亮。最好(最明确)直接使用 for 循环。
for cheese in cheeses: cheese.out_of_stock()
仍然是一个衬里,避免了创建不必要列表的副作用。