我正在尝试实现转发管道功能,例如bash的|
或R的最近%>%
。我已经看到了这个实现http://dev-tricks.net/pipe-infix-syntax-for-python,但是这要求我们事先定义可能与管道一起使用的所有函数。在寻找完全一般的东西时,这就是我到目前为止所想到的。
此函数将其第一个参数应用于其第二个(函数)
def function_application(a,b):
return b(a)
例如,如果我们有一个平方函数
def sq(s):
return s**2
我们可以用这种繁琐的方式调用该函数function_application(5,sq)
。为了更接近正向管道,我们希望将function_application
与中缀表示法一起使用。
从this绘图,我们可以定义一个Infix
类,这样我们就可以用|
等特殊字符包装函数。
class Infix:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __or__(self, other):
return self.function(other)
现在我们可以定义我们的管道,它只是函数function_application
的中缀版本,
p = Infix(function_application)
所以我们可以做这样的事情
5 |p| sq
25
或
[1,2,3,8] |p| sum |p| sq
196
在那个冗长的解释之后,我的问题是,是否有任何方法可以覆盖valid function names的限制。在这里,我已经命名了管道p
,但是可以重载非字母数字字符吗?我可以命名一个函数>
,因此我的管道是|>|
吗?
答案 0 :(得分:5)
你不能在python中真正使用|>|
,至少你需要| * > * |
,其中*
需要是标识符,数字,字符串或其他表达式。
每一行都是一个陈述(simple或compound),stmt
可以是一些东西,其中一个expression,一个表达式是唯一的构造允许使用or operator |
和greater than comparison >
(或所有运算符和比较< > <= >= | ^ & >> << - + % / //
),每个表达式都需要左侧和右侧,最终形式为lhs op rhs
,左右两侧可以是另一个表达式,但退出案例是使用primary(除了常数{{1}只需要-
)的{}},~
和+
,主要部分将归结为标识符,数字或字符串,因此,在一天结束时,您需要在rhs
旁边有一个identifier [a-zA-Z_][a-zA-Z_0-9]*
。
您是否考虑过一种不同的方法,例如一个类覆盖或运算符而不是中缀类?我有tiny library做管道,可能会让你感兴趣
供参考,这是完整的语法:
答案 1 :(得分:2)
我一直在寻找一种方法来做到这一点。所以我创建了一个名为Pypework的Python库。
您只需在每个函数调用的开头添加f.
等前缀,以使其可管理。然后,您可以使用>>
运算符将它们链接在一起,如下所示:
"Lorem Ipsum" >> f.lowercase >> f.replace(" ", "_") # -> "lorem_ipsum"
如果包含在括号中,则跨越多行,如下所示:
(
"Lorem Ipsum"
>> f.lowercase
>> f.replace(" ", "_")
)
# -> "lorem_ipsum"