python 中缀前向管道
python infix forward pipe
我正在尝试实现转发管道功能,例如 bash 的 |
或 R 最近的 %>%
。我见过这个实现 https://mdk.fr/blog/pipe-infix-syntax-for-python.html,但这需要我们预先定义所有可能与管道一起使用的函数。在寻求完全通用的东西时,这是我到目前为止的想法。
这个函数将它的第一个参数应用到它的第二个(一个函数)
def function_application(a,b):
return b(a)
例如,如果我们有一个平方函数
def sq(s):
return s**2
我们可以用这种麻烦的方式调用该函数 function_application(5,sq)
。为了更接近前向管道,我们想使用 function_application
和中缀符号。
借鉴this,我们可以定义一个Infix
class,这样我们就可以用|
等特殊字符包装函数。
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
,但是是否可以重载非字母数字字符?我可以命名一个函数 >
所以我的管道是 |>|
吗?
快速回答:
你不能真正在 python 中使用 |>|
,你至少需要 | * > * |
,其中 *
需要是标识符、数字、字符串,或其他表达式。
长答案:
每一行都是一条语句(simple or compound), a stmt
can be a couple of things, among them an expression, an expression is the only construct that allows the use of or operator |
and greater than comparison >
(or all operators and comparisons for that matter < > <= >= | ^ & >> << - + % / //
), every expression needs a left hand side and a right hand side, ultimatelly being in the form lhs op rhs
, both left and right hand side could be another expression, but the exit case is the use of an primary (with the exception of unnary -
, ~
and +
that need just a rhs
), the primary will boil down to an identifier, number or string, so, at the end of the day you are required to have an identifier [a-zA-Z_][a-zA-Z_0-9]*
旁边是 |
.
您是否考虑过一种不同的方法,例如 class 覆盖 or 运算符而不是中缀 class?我有一个做管道的 tiny library,你可能会感兴趣
作为参考,这里是完整的语法:
我也在寻找一种方法来做到这一点。所以我创建了一个名为 Pypework.
的 Python 库
您只需在每个函数调用的开头添加一个前缀,例如 f.
,使其可通过管道传输。然后您可以使用 >>
运算符将它们链接在一起,如下所示:
"Lorem Ipsum" >> f.lowercase >> f.replace(" ", "_") # -> "lorem_ipsum"
或者如果括在括号中则跨多行,如下所示:
(
"Lorem Ipsum"
>> f.lowercase
>> f.replace(" ", "_")
)
# -> "lorem_ipsum"
我正在尝试实现转发管道功能,例如 bash 的 |
或 R 最近的 %>%
。我见过这个实现 https://mdk.fr/blog/pipe-infix-syntax-for-python.html,但这需要我们预先定义所有可能与管道一起使用的函数。在寻求完全通用的东西时,这是我到目前为止的想法。
这个函数将它的第一个参数应用到它的第二个(一个函数)
def function_application(a,b):
return b(a)
例如,如果我们有一个平方函数
def sq(s):
return s**2
我们可以用这种麻烦的方式调用该函数 function_application(5,sq)
。为了更接近前向管道,我们想使用 function_application
和中缀符号。
借鉴this,我们可以定义一个Infix
class,这样我们就可以用|
等特殊字符包装函数。
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
,但是是否可以重载非字母数字字符?我可以命名一个函数 >
所以我的管道是 |>|
吗?
快速回答:
你不能真正在 python 中使用 |>|
,你至少需要 | * > * |
,其中 *
需要是标识符、数字、字符串,或其他表达式。
长答案:
每一行都是一条语句(simple or compound), a stmt
can be a couple of things, among them an expression, an expression is the only construct that allows the use of or operator |
and greater than comparison >
(or all operators and comparisons for that matter < > <= >= | ^ & >> << - + % / //
), every expression needs a left hand side and a right hand side, ultimatelly being in the form lhs op rhs
, both left and right hand side could be another expression, but the exit case is the use of an primary (with the exception of unnary -
, ~
and +
that need just a rhs
), the primary will boil down to an identifier, number or string, so, at the end of the day you are required to have an identifier [a-zA-Z_][a-zA-Z_0-9]*
旁边是 |
.
您是否考虑过一种不同的方法,例如 class 覆盖 or 运算符而不是中缀 class?我有一个做管道的 tiny library,你可能会感兴趣
作为参考,这里是完整的语法:
我也在寻找一种方法来做到这一点。所以我创建了一个名为 Pypework.
的 Python 库您只需在每个函数调用的开头添加一个前缀,例如 f.
,使其可通过管道传输。然后您可以使用 >>
运算符将它们链接在一起,如下所示:
"Lorem Ipsum" >> f.lowercase >> f.replace(" ", "_") # -> "lorem_ipsum"
或者如果括在括号中则跨多行,如下所示:
(
"Lorem Ipsum"
>> f.lowercase
>> f.replace(" ", "_")
)
# -> "lorem_ipsum"