我目前正在学习Python(来自其他语言,如JavaScript和Ruby),我非常习惯于链接一堆转换/过滤器,但我很确定这不是在Python中做这件事的正确方法:filter
在可枚举的前面有一个lambda,所以编写一个长的/多行的函数看起来很奇怪,链接它们意味着将它们按相反的顺序放置,这是不可读的。
在这个JavaScript函数中编写Map和过滤器的"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);
}
});
我知道我可能会对第一个Map和接下来的两个过滤器使用列表解析,但我不确定如何进行最后一个Map以及如何将所有内容放在一起。
谢谢大家!
8条答案
按热度按时间qcbq4gxm1#
如果你想使用内置的filter,map和reduce方法,你可以在python中使用继承来实现同样的事情,这里我创建了一个名为
my_list
的类,它扩展了class list
,我将用my_list
Package 我的列表,然后通过传递一个函数作为参数来使用从我的类中定义的map,filter和reduce。我知道每次调用这三个方法时都会创建一个新的对象。如果有任何方法可以绕过多个对象的创建,请让我知道。
yws3nbqq2#
如果您不介意使用软件包,那么使用https://github.com/EntilZha/PyFunctional也是一种方法
如前所述,python允许你使用lambba表达式,但是它们不像javascript中的修饰符那样灵活,因为它们不能有一个以上的语句。另一个令人讨厌的python特性是需要反斜杠。话虽如此,我认为以上最接近你最初发布的内容。
免责声明:我是上述软件包的作者
7fyelxc53#
一个很好的方法是将多个过滤器/Map组合成一个生成器理解。如果无法做到这一点,请为所需的中间Map/过滤器定义一个中间变量,而不是试图将这些Map强制为一个链。例如:
注意,Map和过滤器的实际应用都是在最后两行完成的,前面的部分只是定义对Map和过滤器进行编码的函数。
第二个生成器解析同时完成最后两个过滤器和Map。使用生成器解析意味着
inventory
中的每个原始项都将被惰性地Map/过滤。它不会预处理整个列表,因此如果列表很大,它可能会执行得更好。注意,没有Python中的等价物可以像JavaScript示例中那样内联定义long函数,不能内联指定复杂的filter(
item.type == "cake"
),而是必须将其定义为一个单独的函数,就像is_in_stock
和as_item
一样。(The第一个Map被拆分的原因是后面的过滤器在Map后才能作用于Map的数据。它可以合并成一个,但这需要在解析中手动重做
as_item
Map:把Map分离出来会更清楚。)
c6ubokkw4#
使用迭代器(在python3中所有这些函数都是迭代器,在python2中你需要使用itertools.imap和itertools.ifilter)
xvw2m8pv5#
定义你自己的函数组合元函数是非常容易的。一旦你有了它,把函数链接在一起也是非常容易的。
如果您还不熟悉迭代器,如果我是您,我会温习一下(类似http://excess.org/article/2013/02/itergen1/的东西很好)。
0h4hbjxa6#
bjp0bcyl7#
我们可以使用Pyterator:https://github.com/remykarem/pyterator(免责声明:我是作者),和@EntilZha的图书馆很像。
定义功能
那么
注意,像
map
和filter
这样的所有操作都是延迟求值的,所以你需要调用.to_list()
来求值管道,否则,它将保持为Iterator
(你可以在以后的for循环中使用它)。也类似于Fluentpy(https://github.com/dwt/fluent)。
0tdrvxhp8#
您可以在生成器理解中使用walrus操作符来实现这一点。
但是您必须分配不同的变量(示例中的
x/y/z
),因为您不能使用walrus操作符分配给现有变量。完整示例