Python 中的所有内容都是对象,为什么运算符不是?

Everything in Python is an object, why operators are not?

Everything in Python is an object

我们都知道这句话,所有 Python 爱好者(包括我)都喜欢它。在这方面,看看运营商是很有趣的。它们似乎不是物体,例如

>>> type(*)     # or /, +, -, < ...

returns SyntaxError: invalid syntax

但是,在某些情况下,将它们视为对象可能会很有用。例如考虑一个像

这样的函数
def operation(operand1, operand2, operator):
    """
    This function returns the operation of two operands defined by the operator as parameter
    """

    # The following line is invalid python code and should only describe the function
    return operand1 <operator> operand2

所以operation(1, 2, +)会return3,operation(1, 2, *)会return2,operation(1, 2, <)会return True,等等...

为什么 python 中没有实施?或者是,如果,如何?


备注:我知道operator模块,它也不适用于上面的示例函数。我也知道可以通过一种方式解决它,例如operations(operand1, operand2, '>') 并通过相应运算符的字符串表示找到所需的操作。但是,我要问的是不存在能够作为函数中的参数传递的运算符对象的原因,例如像所有其他 python 对象一样。

每个都是一个对象。运算符不是值;它们是语法。然而,它们是由函数实现的,函数是值。 operator 模块提供对这些功能的访问。


完全不适用于 Python,尽管具有启发性,但语言 可以 提供额外的语法来将运算符转换为 "name"。例如,在 Haskell 中,您可以使用像 + 这样的中缀运算符,就好像它是一个使用括号的名称一样。你想在 Python 中写 operation(3, 5, +) 的地方, Haskell 允许 operation 3 5 (+).

没有 技术 不能将类似内容添加到 Python 的原因,但也没有令人信服的 设计添加它的原因。 operator 模块就足够了,"fits" 与整个语言设计更好。

运算符告诉解释器底层方法对提供的对象进行操作,所以它们更像函数,在某种意义上仍然是对象,你只需要适当的引用调用 type。例如,假设您有 Foo.some_method 并且您想要查找它的类型。您需要正确的参考:type(Foo.some_method) 而不仅仅是 type(some_method),其中第一个 returns <class 'function'>,后者 NameError.

就是说,您当然可以在没有 operator 模块的情况下实现这样的功能:

def operation(operand1, operand2, operator):
    return getattr(operand1, operator)(operand2)

operation(1, 2, '__add__')
# 3

也就是说,理解您的问题的最简单方法是运算符是 python 语法的一部分来解释您的代码,而不是实际对象。因此,当解释器看到 *+~ 等时...它期望两个操作数获取别名方法并执行。方法本身是一个对象。语法,没那么多。

您可以将运算符视为一种语法糖。例如,3+4 只是 int.__add__(3,4) 的语法糖。 type(int.__add__) 不是 None 但 type(+) 会引发错误。

你说:

    # The following line is invalid python code and should only describe the function
    return operand1 <operator> operand2

这不是真的,该代码并非无效。使用配件 operator,它确实按预期工作:

def operation(operand1, operand2, operator):
    """
    This function returns the operation of two operands defined by the operator as parameter
    """
    return operand1 <operator> operand2

class Subtraction:
    def __gt__(self, operand):
        try:
            return self.operand - operand
        except:
            self.operand = operand
            return self

print(operation(13, 8, Subtraction()))

按预期打印 5

这是一个很好的问题的例子。
从技术上讲,要正确回答这个问题,除了编码声明、注释和空行之外,还可以使用词法分析器(分词器)方法来区分分词类别。

除了运算符,还有:i) NEWLINE、INDENT 和 DEDENT,ii) 关键字,以及 iii) 定界符 不是对象。 其他所有内容都是 Python 中的对象。

所以下次他们告诉你“Python 中的一切都是对象”时你应该回答:
“逻辑行中除 NEWLINE、INDENT、DEDENT、Space bar Character、Operator、Keyword 或 Delimiter 之外的所有内容都是 Python 中的对象。”

这里的基本原理尝试:当 Python 设计者设计语言时,他们认为这些标记类别在任何情况下都几乎无用,无法通过其他方式解决。 .
干杯。