我目前正在学习 Python(来自 JavaScript 和 Ruby 等其他语言)。我非常习惯链接一堆转换/过滤器,但我很确定这不是在 Python 中执行此操作的正确方法: filter
在可枚举之前采用 lambda,因此编写 long / multi -line 函数看起来真的很奇怪,将它们链接在一起意味着将它们按相反的顺序放置,这是不可读的。
在此 JavaScript 函数中编写映射和过滤器的“Python 方式”是什么?
let is_in_stock = function() /* ... */
let as_item = function() /* ... */
let low_weight_items = shop.inventory
.map(as_item)
.filter(is_in_stock)
.filter(item => item.weight < 1000)
.map(item => {
if (item.type == "cake") {
let catalog_item = retrieve_catalog_item(item.id);
return {
id: item.id,
weight: item.weight,
barcode: catalog_item.barcode
};
} else {
return default_transformer(item);
}
});
我知道我可能会对第一张地图和接下来的两个过滤器使用列表理解,但我不确定如何做最后一张地图以及如何将所有内容放在一起。
谢谢!
原文由 Edward 发布,翻译遵循 CC BY-SA 4.0 许可协议
一个好的方法是将多个过滤器/映射组合成一个生成器理解。在无法做到这一点的情况下,为您需要的中间映射/过滤器定义一个中间变量,而不是试图将映射强制到一个链中。例如:
请注意,地图和过滤器的实际应用都在最后两行中完成。前面的部分只是定义对映射和过滤器进行编码的函数。
第二个生成器理解将最后两个过滤器和映射一起执行。使用生成器理解意味着
inventory
中的每个原始项目将被延迟映射/过滤。它不会预处理整个列表,因此如果列表很大,它的性能可能会更好。请注意,没有 Python 等同于在您的 JavaScript 示例中定义内联长函数。您不能内联指定复杂过滤器(带有
item.type == "cake"
的过滤器)。相反,如我的示例所示,您 必须 将其定义为单独的函数,就像您对is_in_stock
和as_item
的那样。(第一个地图被拆分的原因是后面的过滤器在映射之后才能对映射数据进行操作。它可以组合成一个,但这需要手动重做
as_item
理解内的地图:把那张地图分开会更清楚。)