python中的功能管,如从dplyr的%>% [英] functional pipes in python like %>% from dplyr

查看:137
本文介绍了python中的功能管,如从dplyr的%>%的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在R中(感谢 dplyr ),您现在可以通过%>%。这意味着代替编码:

 > as.Date(2014-01-01)
> as.character((sqrt(12)^ 2)

你也可以这样做:

 >2014-01-01%>%as.Date 
> 12%>%sqrt% >%。^ 2%>%as.character

对我来说,这更可读,扩展到数据框之外的用例,python语言是否支持类似的东西?

解决方案

通过使用一个名为 macropy 的模块,Macropy允许您将转换应用于因此,您可以将 a | b 转换为 b(a),其中包含优点和缺点。



与Sylvain Leroux提到的解决方案相比,主要优点是您不需要为您感兴趣的功能创建infix对象 - 只是标记你打算使用的代码区域他转型。其次,由于转换在编译时而不是运行时应用,所以转换后的代码在运行时不受任何开销 - 所有的工作都是在源代码首次生成时完成的。



主要的缺点是,熵需要一定的激活方式使其工作(稍后提及)。与更快的运行时相比,源代码的解析在计算上更复杂,因此该程序将需要更长的时间才能启动。最后,它增加了一种句法风格,这意味着不熟悉宏观的程序员可能会发现你的代码更难理解。



示例代码:



run.py

  import macropy.activate 
#激活macropy,使用macropy的模块无法在该语句
#之前导入。
import target
#导入模块使用macropy

目标。从

  from fpipe import macros,fpipe 
from macropy.quick_lambda import macros,f
#`从模块导入宏,...`必须用于macropy来知道哪些
#宏应该适用于你的代码。
#这里有两个宏已经导入`fpipe`,这样做你想要的
#和`f`可以更快地编写lambdas。

从数学导入sqrt

#在单个表达式中使用fpipe宏。
#方括号之间的代码解释为 - str(sqrt(12))
print fpipe [12 | sqrt | str]#打印3.46410161514

#使用装饰器
#对函数中的所有代码进行了检查, y`构造。
x = 1#全局变量
@fpipe
def sum_range_then_square():
期望值(1 + 2 + 3)** 2 - > 36
y = 4#局部变量
返回范围(x,y)|总和| f [_ ** 2]
#`f [_ ** 2]`是 - lambda x:x ** 2的macropy语法,这也可以在这里工作

print sum_range_then_square()#prints 36

#using a with block。
#与装饰器相同,但对于有限的块。
with fpipe:
print range(4)| sum#prints 6
print'a b c'| f [_。split()]#打印['a','b','c']

最后这个模块做的很努力。我把它称为fpipe作为功能管道,用于将输出从一个进程传递给另一个进程的模拟shell语法。



fpipe.py 来自macropy.core.macros import的

 来自macropy.core.quotes的
导入宏,q,ast

宏= Macros()

@ macros.decorator
@ macros.block
@ macros.expr
def fpipe(tree,** kw) :

@Walker
def pipe_search(tree,stop,** kw):
按位或运算符搜索代码,并将`a | b'转换为`b (a)`。
如果isinstance(tree,BinOp)和isinstance(tree.op,BitOr):
operand = tree.left
function = tree.right
newtree = q [ast [function](ast [operand])]
return newtree

return pipe_search.recurse(tree)
pre>

In R (thanks to dplyr) you can now perform operations with a more functional piping syntax via %>%. This means that instead of coding this:

> as.Date("2014-01-01")
> as.character((sqrt(12)^2)

You could also do this:

> "2014-01-01" %>% as.Date 
> 12 %>% sqrt %>% .^2 %>% as.character

To me this is more readable and this extends to use cases beyond the dataframe. Does the python language have support for something similar?

解决方案

One possible way of doing this is by using a module called macropy. Macropy allows you to apply transformations to the code that you have written. Thus a | b can be transformed to b(a). This has a number of advantages and disadvantages.

In comparison to the solution mentioned by Sylvain Leroux, The main advantage is that you do not need to create infix objects for the functions you are interested in using -- just mark the areas of code that you intend to use the transformation. Secondly, since the transformation is applied at compile time, rather than runtime, the transformed code suffers no overhead during runtime -- all the work is done when the byte code is first produced from the source code.

The main disadvantages are that macropy requires a certain way to be activated for it to work (mentioned later). In contrast to a faster runtime, the parsing of the source code is more computationally complex and so the program will take longer to start. Finally, it adds a syntactic style that means programmers who are not familiar with macropy may find your code harder to understand.

Example Code:

run.py

import macropy.activate 
# Activates macropy, modules using macropy cannot be imported before this statement
# in the program.
import target
# import the module using macropy

target.py

from fpipe import macros, fpipe
from macropy.quick_lambda import macros, f
# The `from module import macros, ...` must be used for macropy to know which 
# macros it should apply to your code.
# Here two macros have been imported `fpipe`, which does what you want
# and `f` which provides a quicker way to write lambdas.

from math import sqrt

# Using the fpipe macro in a single expression.
# The code between the square braces is interpreted as - str(sqrt(12))
print fpipe[12 | sqrt | str] # prints 3.46410161514

# using a decorator
# All code within the function is examined for `x | y` constructs.
x = 1 # global variable
@fpipe
def sum_range_then_square():
    "expected value (1 + 2 + 3)**2 -> 36"
    y = 4 # local variable
    return range(x, y) | sum | f[_**2]
    # `f[_**2]` is macropy syntax for -- `lambda x: x**2`, which would also work here

print sum_range_then_square() # prints 36

# using a with block.
# same as a decorator, but for limited blocks.
with fpipe:
    print range(4) | sum # prints 6
    print 'a b c' | f[_.split()] # prints ['a', 'b', 'c']

And finally the module that does the hard work. I've called it fpipe for functional pipe as its emulating shell syntax for passing output from one process to another.

fpipe.py

from macropy.core.macros import *
from macropy.core.quotes import macros, q, ast

macros = Macros()

@macros.decorator
@macros.block
@macros.expr
def fpipe(tree, **kw):

    @Walker
    def pipe_search(tree, stop, **kw):
        """Search code for bitwise or operators and transform `a | b` to `b(a)`."""
        if isinstance(tree, BinOp) and isinstance(tree.op, BitOr):
            operand = tree.left
            function = tree.right
            newtree = q[ast[function](ast[operand])]
            return newtree

    return pipe_search.recurse(tree)

这篇关于python中的功能管,如从dplyr的%>%的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆