面向人类的Python函数式编程。

nonion的Python项目详细描述


非离子

NOnion是一个提供函数式编程工具的Python包。它旨在消除嵌套函数调用,如z(g(f(x)),这些调用会提醒onion。在

安装

pip install nonion

教程

非离子包含两个主要概念:

  • Function—一个anyPythonCallable的包装器
  • Pipeline—一个anyPythonIterable的包装器。在

函数

为了创建函数,只需传递任何Callable

^{pr2}$

您还可以创建标识函数

g=Function()

请注意,函数只接受一个值并返回一个值。在

撰写

定义为$(f\circ g)(x)=f(g(x))$的“函数组合”可以通过以下方式完成:

z=f@g# alternativelyz=f.compose(g)

您还可以多次使用compose

z=f@g@f

与用函数包装每个Callable不同的是,您只能先包装firstCallable,其余部分使用compose。在

deff(x):returnx+1g=Function()@(lambdax:x*2)@fg(5)# returns 12

使用了@(at)运算符,因为它提醒$\circ$符号。在

然后

函数组合有时可能很难读懂,因为必须从右向左读。 为了获得更好的可读性,可以使用then。在

g=Function()/(lambdax:x*2)/fg(5)# returns 11# alternativelyg=Function().then(lambdax:x*2).then(f)g(5)# returns 11

使用了/(斜杠)运算符,因为它提醒用于管道的$(竖线)。在

呼叫

有时您希望在多次组合之后调用函数“inline”。在这种情况下,您可以使用:

(Function()/(lambdax:x*2)/f)(5)# returns 11

但这可能很难读懂。尤其是当你大部分时间都是通过兰姆达斯的时候。调用函数的更好方法是使用:

Function()/(lambdax:x*2)/f&5# returns 11

使用了&;(和号)运算符,因为它看起来类似于$(dollar),后者是Haskell运算符。在

星形(功能)

假设您定义了一个具有多个参数的函数,例如:

deff(x,y):returnx+y*x

你想用函数包装这个函数。在本例中,必须使用star。在

Function()@star(f)&(1,2)# returns 5

star只是使用Python *(star)运算符将参数传递给函数。在

foreach

您还可以按以下方式为某个Iterable中的每个值调用一个函数:

ys=Function()/(lambdax:x*2)/(lambdax:x+1)*range(5)foryinys:print(y)# 1# 3# 5# 7# 9#

使用了*(star)运算符,因为没有将Iterable传递给函数,而是将其内容作为Python*(star)运算符和采用*args的函数传递。在

管道

为了创建Pipeline,只需传递任何Iterable

xs=Pipeline(range(5))# notation abuse, do not use that:xs=Function()/Pipeline&range(5)

您还可以创建一个空的管道

xs=Pipeline()

{emm}简单地在emm}下传递Iterable,那么您只需在Pipeline上迭代一次。在

xs=Pipeline(range(2))forxinxs:print(x)# 1# 2## perfectly fine, because range(x) returns a special objectforxinxs:print(x)# 1# 2#xs=Pipeline(xforxinrange(2))forxinxs:print(x)# 1# 2## xs already exhaustedforxinxs:print(x)

地图

map允许您对Pipeline的每个值调用一个Callable,它接受一个值并返回一个值。在

ys=Pipeline(range(3))/(lambdax:x+1)/(lambdax:(x,x+1))/star(lambdax,y:x+y*x)foryinys:print(y)# 3# 8# 15## alternativelyys=Pipeline(range(3)).map(lambdax:x+1).map(lambdax:(x,x+1)).map(star(lambdax,y:x+y*x))

使用了/(斜杠)运算符,因为它提醒用于管道的$(竖线)。在

过滤器

filter允许您过滤Pipeline值。在

ys=Pipeline(range(3))%(lambdax:x>1)foryinys:print(y)# 2## alternativelyys=Pipeline(range(3)).filter(lambdax:x>1)

平面图

flatmap允许您调用一个Callable,它接受一个值并在Pipeline的每个值上返回一个Iterable,并将结果展平为单个Pipeline。在

ys=Pipeline(range(2))/(lambdax:x+1)*(lambdax:(x,x+1))foryinys:print(y)# 1# 2# 2# 3## alternativelyys=Pipeline(range(2)).map(lambdax:x+1).flatmap(lambdax:(x,x+1))

使用了*(star)运算符,因为直观地您使用的是Python*(star)运算符。在

应用

apply允许调用Callable,它接受一个Iterable,并返回一个Iterable。在

ys=Pipeline(range(2))/(lambdax:x+1)//tuple# internally Pipeline now has a tupleforyinys:print(y)# 1# 2## now multiple itertations is possibleforyinys:print(y)# 1# 2## alternativelyys=Pipeline(range(2)).map(lambdax:x+1).apply(tuple)

收集

{emm{emm>允许任何apply和collect的区别在于,collect返回函数的结果,而不是用Pipeline包装它。在

ys=Pipeline(range(2))/(lambdax:x+1)>>tupleprint(ys)# (1, 2)## alternativelyys=Pipeline(range(2)).map(lambdax:x+1).collect(tuple)

foreach

foreach允许您对Pipeline的每个值调用一个Callable,它接受一个值。在

^{pr21}$

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
由于测试失败,java testcontainers maven构建失败   java实现jacobi算法实现laplace方程   java中的多线程:如何在不等待所有线程使用ExecutorService完成任务的情况下终止所有线程的执行?   java Hello World不在Android Studio 3中工作   ubuntu Tomcat7的Java版本不正确   java Javafx内存泄漏   对于手动实现的Spring数据存储库方法,我应该使用Java8默认方法吗?   googleappengine中的java添加过滤查询   html当使用JSOUP库在Java中读取标签时,如何保留标签(如<br>、<ul>、<li>、<p>等)的含义?   编码为什么jasper生成的报告在Java中不显示西里尔语(保加利亚语)?   java有没有办法隐藏当前位置和jdk动作?   java找出编译原型文件的版本   有没有办法在运行时更改java方法的访问修饰符?   语法字符串。。。Java中的参数   java数组元素在添加其他元素时会相互覆盖   eclipse中的java GWT项目   java如何为spring rest模板请求将动态json属性名映射到jackson   java无法在Windows 10上找到特定的JDK   在xml字符串和java字符串之间提取正则表达式子字符串