xxx*_*--- 4 python operators operator-keyword
为表示我们可以定义的Python的内在运营商这里.只是为了好奇,我们可以定义像$或的新运算符***吗?(如果是这样,那么我们可以定义三元条件运算符或旋转运算符.)
正如@minitech所说,你无法定义新的运营商.但是检查这个允许你定义中缀运算符的hack http://code.activestate.com/recipes/384122-infix-operators/
扩展@fasouto 答案,但添加更多代码。
\n虽然您不能定义新的运算符,也不能为内置类型重新定义现有的运算符,但您可以做的是定义一个类(实例化为任何有效的 Python 名称,例如op)作为两个对象的中间绑定,从而有效地查找就像二元中缀运算符:
a | op | b\nRun Code Online (Sandbox Code Playgroud)\n简而言之,可以为运算符定义一个覆盖前向和后向__or__方法的类,例如和__ror__运算|符:
class Infix:\n def __init__(self, function):\n self.function = function\n def __ror__(self, other):\n return Infix(lambda x, self=self, other=other: self.function(other, x))\n def __or__(self, other):\n return self.function(other)\n def __call__(self, value1, value2):\n return self.function(value1, value2)\nRun Code Online (Sandbox Code Playgroud)\n这个可以直接使用:
\nop = Infix(lambda a, b: a + b) # can be any bivariate function\n\n1 | op | 2\n# 3\nRun Code Online (Sandbox Code Playgroud)\n或作为装饰器:
\n@Infix\ndef op(a, b):\n return a + b\n\n1 | op | 2\n# 3\nRun Code Online (Sandbox Code Playgroud)\n上面的解决方案按原样工作,但存在一些问题,例如表达式不能单独op | 2使用:
op = Infix(lambda a, b: a + b)\n(1 | op)\n#<__main__.Infix object at 0x7facf8f33d30>\n\n# (op | 2)\n# TypeError: <lambda>() missing 1 required positional argument: \'b\'\n\n(1 | op | 2)\n# 3\nRun Code Online (Sandbox Code Playgroud)\n为了获得正确的绑定,需要编写一些更复杂的代码来执行中间绑定:
\nclass Infix(object):\n def __init__(self, func):\n self.func = func\n\n class RBind:\n def __init__(self, func, binded):\n self.func = func\n self.binded = binded\n def __call__(self, other):\n return self.func(other, self.binded)\n __ror__ = __call__\n\n class LBind:\n def __init__(self, func, binded):\n self.func = func\n self.binded = binded\n def __call__(self, other):\n return self.func(self.binded, other)\n __or__ = __call__\n\n def __or__(self, other):\n return self.RBind(self.func, other)\n\n def __ror__(self, other):\n return self.LBind(self.func, other)\n\n def __call__(self, value1, value2):\n return self.func(value1, value2)\nRun Code Online (Sandbox Code Playgroud)\n使用方式与以前相同,例如:
\nop = Infix(lambda a, b: a + b)\nRun Code Online (Sandbox Code Playgroud)\n或作为装饰器:
\n@Infix\ndef op(a, b):\n return a + b\nRun Code Online (Sandbox Code Playgroud)\n这样,人们就会得到:
\n1 | op\n# <__main__.Infix.LBind object at 0x7facf8f2b828>\n\nop | 2\n# <__main__.Infix.RBind object at 0x7facf8f2be10>\n\n1 | op | 2\n# 3\nRun Code Online (Sandbox Code Playgroud)\n还有一个 PyPI 包(我与它没有任何关系)基本上实现了这一点: https: //pypi.org/project/infix/
\n顺便说一句,绑定解决方案似乎也稍微快一些:
\n%timeit [1 | op | 2 for _ in range(1000)]\n\n# Non-binding implementation\n# 1000 loops, best of 3: 626 \xc2\xb5s per loop\n\n# Binding implementation\n# 1000 loops, best of 3: 525 \xc2\xb5s per loop\nRun Code Online (Sandbox Code Playgroud)\n这些实现使用|,但可以使用任何二元运算符:
+:__add__-:__sub__*:__mul__/:__truediv__//:__floordiv__%:__mod__**:__pow__@:(__matmul__适用于 Python 3.5 及以上版本)|:__or__&:__and__^:__xor__>>:__rshift__<<:__lshift__这**将需要绑定实现或调整非绑定实现以反映运算符是右关联的。上面的所有其他运算符要么是左结合的(-, /, //, %, @, >>, <<),要么是直接交换的(+, *, |, &, ^)。
请记住,这些运算符都与普通 Python 运算符具有相同的优先级,因此,例如:
\n(1 | op | 2 * 5) == (1 | op | (2 * 5)) != ((1 | op | 2) * 5)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1299 次 |
| 最近记录: |