python中是否有地图的运算符形式?

时间:2016-09-29 12:28:08

标签: python functional-programming

在Mathematica中,可以将Map [f,list]写为f / @ list,其中/ @是Map的运算符形式。在python中有map(f,list)但有类似的运算符表单或提供此的包吗?

应用程序是使用许多映射的深层嵌套转换最终会有很多括号,而操作符链可以更容易阅读(和键入)。

1 个答案:

答案 0 :(得分:2)

没有简单的方法可以做到这一点。 Python没有提供任何方法来定义自定义运算符,它提供的运算符集非常标准,主要用于数字和字符串之类的东西。 map对象不支持这样的内容,但没有什么能阻止您编写自己的类:

class Mapper:
    def __init__(self, f):
        self.f = f
    def __matmul__(self, other):
        return map(self.f, other)

用作:

In [3]: list(Mapper(lambda x: x+1) @ [1,2,3,4,5])
Out[3]: [2, 3, 4, 5, 6]

您可以类似地介绍Filter类:

class Filter:
    def __init__(self, p):
        self.p = p
    def __matmul__(self, other):
        return filter(self.p, other)

用作:

In [5]: list(Filter(lambda x: x%2==0) @ range(10))
Out[5]: [0, 2, 4, 6, 8]

事实上你可以看到这种类几乎都是相同的,所以你可以概括它们。

注意:@作为运算符是python3.5的新功能。

使用此问题的一个问题是@ 关联,这意味着您无法撰写此功能。您可以使用类似**的正确关联的内容来轻松编写它们:

class Filter:
    def __init__(self, p):
        self.p = p
    def __pow__(self, other):
        return filter(self.p, other)

class Mapper:
    def __init__(self, f):
        self.f = f
    def __pow__(self, other):
        return map(self.f, other)

允许:

In [13]: Filter(lambda x: x%2==0) ** Mapper(lambda x: x+1) ** range(10)
Out[13]: <filter at 0x7fe0696bcd68>

为了完整性:这是一个实现,它概括了这个概念,并且通过组合转换也可以与@一起使用:

class Apply:
    def __init__(self, f):
        self.f = f
    def __matmul__(self, seq_or_apply):
        if isinstance(seq_or_apply, Apply):
            return Apply(lambda seq: self.f(seq_or_apply.f(seq)))
        return self.f(seq_or_apply)

class Mapper(Apply):
    def __init__(self, f):
        super().__init__(lambda x: map(f, x))

class Filter(Apply):
    def __init__(self, p):
        super().__init__(lambda x: filter(p, x))

from functools import reduce

class Reduce(Apply):
    def __init__(self, op, init):
        super().__init__(lambda seq: reduce(op, seq, init))

用作:

In [26]: import operator as op
In [27]: Reduce(op.add, -7) @ Filter(lambda x: x%2==0) @ Mapper(lambda x: x+1) @ range(10)
Out[27]: 23