扩展@fasouto答案,但添加更多代码。
虽然您不能定义新的运算符,也不能为内置类型重新定义现有的运算符,但是您可以做的是定义一个类(实例化为任何有效的Python名称
op),该类充当两个对象的中间绑定,从而有效地查找像二进制中缀运算符一样:
非约束性实施a | op | b
总之,可以定义一个类中重写 向前 和 向后 *** 作员,例如使用的方法
__or__和
__ror__用于
|*** 作者:
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) def __call__(self, value1, value2): return self.function(value1, value2)
可以直接使用:
op = Infix(lambda a, b: a + b) # can be any bivariate function1 | op | 2# 3
或作为装饰者:
@Infixdef op(a, b): return a + b1 | op | 2# 3
上述解决方案工作方式是,但也存在一些问题,如
op | 2表达不能用 单纯 :
op = Infix(lambda a, b: a + b)(1 | op)#<__main__.Infix object at 0x7facf8f33d30># op | 2# TypeError: <lambda>() missing 1 required positional argument: 'b'1 | op | 2)# 3
绑定实现
为了获得适当的绑定,需要编写一些更复杂的代码来执行中间 绑定 :
class Infix(object): def __init__(self, func): self.func = func class RBind: def __init__(self, func, binded): self.func = func self.binded = binded def __call__(self, other): return self.func(other, self.binded) __ror__ = __call__ class LBind: def __init__(self, func, binded): self.func = func self.binded = binded def __call__(self, other): return self.func(self.binded, other) __or__ = __call__ def __or__(self, other): return self.RBind(self.func, other) def __ror__(self, other): return self.LBind(self.func, other) def __call__(self, value1, value2): return self.func(value1, value2)
使用方法与以前相同,例如:
op = Infix(lambda a, b: a + b)
或作为装饰者:
@Infixdef op(a, b): return a + b
有了这个,就会得到:
1 | op# <__main__.Infix.LBind object at 0x7facf8f2b828>op | 2# <__main__.Infix.RBind object at 0x7facf8f2be10>1 | op | 2# 3
还有一个PyPI软件包,基本上实现了此功能:https :
//pypi.org/project/infix/
顺便说一句,绑定解决方案似乎也快一些:
笔记%timeit [1 | op | 2 for _ in range(1000)]# Non-binding implementation# 1000 loops, best of 3: 626 µs per loop# Binding implementation# 1000 loops, best of 3: 525 µs per loop
这些实现使用
|,但是可以使用任何二进制运算符:
+
:__add__
-
:__sub__
*
:__mul__
/
:__truediv__
//
:__floordiv__
%
:__mod__
**
:__pow__
@
:(__matmul__
适用于Python 3.5及更高版本)|
:__or__
&
:__and__
^
:__xor__
>>
:__rshift__
<<
:__lshift__
这
**需要绑定实现或调整非绑定实现以反映 *** 作符是 右关联的 。从上面的所有其他运营商要么 左结合
(
-,
/,
//,
%,
@,
>>,
<<),或直接交换(
+,
*,
|,
&,
^)。
请记住,它们都将具有与普通Python运算符相同的优先级,因此,例如:
(1 | op | 2 * 5) == (1 | op | (2 * 5)) != ((1 | op | 2) * 5)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)