您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python中的新运算符

Python中的新运算符

扩展@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 function

1 | op | 2
# 3

或作为装饰者:

@Infix
def op(a, b):
    return a + b

1 | 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)

或作为装饰者:

@Infix
def 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

这些实现使用|,但是可以使用任何二进制运算符:

**需要绑定实现或调整非绑定实现以反映操作符是 右关联的 。从上面的所有其他运营商要么 左结合-///%@>><<),或直接交换(+*|&^)。

请记住,它们都将具有与普通Python运算符相同的优先级,因此,例如:

(1 | op | 2 * 5) == (1 | op | (2 * 5)) != ((1 | op | 2) * 5)
python 2022/1/1 18:30:10 有184人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶