一种可行的方法是使用名为的模块
macropy。Macropy允许您将转换应用于所编写的代码。因此
a| b可以转换为
b(a)。这具有许多优点和缺点。
与Sylvain Leroux提到的解决方案相比,主要优点是您不需要为要使用的功能创建中缀对象-
只需标记要使用转换的代码区域即可。其次,由于转换是在编译时而不是在运行时应用的,因此转换后的代码在运行时不会受到开销-
所有工作都是在最初从源代码生成字节代码时完成的。
主要缺点是,宏需要某种特定的激活方式才能起作用(稍后会提到)。与更快的运行时间相比,源代码的解析在计算上更加复杂,因此程序将需要更长的启动时间。最后,它添加了一种语法样式,这意味着不熟悉宏的程序员可能会发现您的代码更难理解。
示例代码:
运行
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, fpipefrom 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 pre.# 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 pre between the square braces is interpreted as - str(sqrt(12))print fpipe[12 | sqrt | str] # prints 3.46410161514# using a decorator# All pre within the function is examined for `x | y` constructs.x = 1 # global variable@fpipedef 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 hereprint 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']
最后是完成工作的模块。我称它为功能管道的fpipe,是它的模拟shell语法,用于将输出从一个进程传递到另一个进程。
fpipe.py
from macropy.core.macros import *from macropy.core.quotes import macros, q, astmacros = Macros()@macros.decorator@macros.block@macros.exprdef fpipe(tree, **kw): @Walker def pipe_search(tree, stop, **kw): """Search pre 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)



