器→工具, 开源项目

Python管道工具Pipe

钱魏Way · · 1 次浏览

在先前的文章中,我们介绍了Linux中的管道工具,也学习了Scikit-Learn中的Pipeline。今天再来说一下如何在Python中使用管道操作,使得带来逻辑更加简单易懂。

案例展示

任务:给定一个整数数组,编写一个程序将3与所有奇数整数相乘。

解决方案很简单:

arr = [2, 3, 4, 5, 6, 7]
output = []
for i in arr:
    if i % 2 != 0:
        output.append(i * 3)
print(output)

一个更好的方式是使用Python自带的函数式编程方法map 和 filter。具体代码为:

arr = [2, 3, 4, 5, 6, 7]
output = list(map(lambda x: x * 3, filter(lambda x: x % 2 != 0, arr)))
print(output)

代码虽然简单,但是看起来还是有些混来,再来看看如何使用Pipe工具实现以上需求:

from pipe import select, where

arr = [2, 3, 4, 5, 6, 7]
output = list(arr | where(lambda x: x % 2 != 0) | select(lambda x: x * 3))
print(output)

是不是逻辑更加清晰了?

Python Pipe库简介

Pipe 是一个 Python 库,可让你在 Python 中使用管道。 管道 (|) 将一种方法的结果传递给另一种方法。Pipe将多个方法应用于 Python 可迭代对象时看起来更简洁。由于 Pipe 只提供了几个方法,所以学习Pipe也很容易。 要安装Pipe,请输入:pip install pipe

where:可迭代对象中的过滤元素

与 SQL 类似,Pipe 的 where 方法也可用于过滤可迭代对象中的元素。

select:将函数应用于可迭代对象

select方法类似于map方法。 select 将方法应用于可迭代的每个元素。

现在,你可能想知道:如果 map 和 filter 具有相同的功能,为什么我们需要 where 和 select 方法?这是因为你可以使用管道在另一个方法之后插入一个方法。 因此,使用管道消除了嵌套的括号并使代码更具可读性。

from pipe import select, where

arr = [2, 3, 4, 5, 6, 7]
output = list(arr 
              | where(lambda x: x % 2 != 0) 
              | select(lambda x: x * 3)
              )
print(output)

chain方法:使用 chain 来链接一系列可迭代对象

from pipe import chain

arr = [[1, 2, [3]], [4, 5]]

output = list(arr | chain)
print(output)
# [1, 2, [3], 4, 5]

尽管应用 chain 可以使可迭代对象的嵌套较少,我们仍然需要一个更强大的工具。 为了处理深度嵌套的列表,我们可以使用 traverse 代替。

traverse:递归展开可迭代对象

traverse 方法可用于递归展开可迭代对象。 你可以使用此方法将深度嵌套的列表转换为平面列表。

from pipe import traverse

arr = [[1, 2, [3]], [4, 5]]

output = list(arr | traverse)
print(output)
# [1, 2, 3, 4, 5]

让我们将此方法与 select 方法集成以获取字典的值并展平列表。

from pipe import traverse, select

fruits = [
    {"name": "apple", "price": [2, 5]},
    {"name": "orange", "price": 4},
    {"name": "grape", "price": 5}
]

output = list(fruits | select(lambda fruit: fruit["price"]) | traverse)
print(output)
# [2, 5, 4, 5]

groupby:将列表中的元素分组

有时,使用特定函数对列表中的元素进行分组可能很有用。 这可以通过 groupby 方法轻松完成。

为了看看这个方法是如何工作的,让我们把一个数字列表变成一个字典,这个字典根据数字是偶数还是奇数来分组。

from pipe import groupby, select

items = range(10)
output = list(items | groupby(lambda x: "Odd" if x % 2 else "Even") | select(
    lambda x: "{}: {}".format(x[0], list(x[1]))))
print(output)
# ['Even: [0, 2, 4, 6, 8]', 'Odd: [1, 3, 5, 7, 9]']

dedup 方法删除列表中的重复

这听起来可能并不有趣,因为 set 方法可以做同样的事情。

from pipe import dedup

output = list([-1, 0, 0, 0, 1, 2, 3] | dedup))
print(output)
#[-1, 0, 1, 2, 3]

但是,此方法更灵活,可以让你获取唯一元素。例如,你可以使用此方法获取一个小于 5 的唯一元素和另一个大于或等于 5 的唯一元素。

from pipe import dedup

arr = [1, 2, 2, 3, 4, 5, 6, 6, 7, 9, 3, 3, 1]
output = list(arr | dedup(lambda x: x < 5))
print(output)
# [1, 5]

更多内容请查看官方文档。

参考链接:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注