Python比较运算符<和>如何使用函数名作为操作数?

Cua*_*due 16 python

抛出这个问题(在Python 2.7.5中)有一点错字:

def foo(): return 3
if foo > 8:
    launch_the_nukes()
Run Code Online (Sandbox Code Playgroud)

当它,我不小心爆炸了月亮.

我的理解是,E > F相当于(E).__gt__(F)和表现良好的类(如内置)相当于(F).__lt__(E).

如果没有__lt____gt__运营商那么我认为Python使用__cmp__.

但是,这些方法都与工作function对象,而<>运营商的工作.引擎盖下发生了什么?

>>> foo > 9e9
True
>>> (foo).__gt__(9e9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__gt__'
>>> (9e9).__lt__(foo)
NotImplemented
Run Code Online (Sandbox Code Playgroud)

Mar*_*cin 13

但是,当<和>运算符工作时,这些方法都不适用于函数对象.引擎盖下发生了什么?

在默认的任何其他合理比较中,2.x系列中的CPython基于类型名称进行比较.(这被记录为实现细节,尽管有一些有趣的例外情况只能在源代码中找到.)在3.x系列中,这将导致异常.

Python规范对2.x中的行为设置了一些特定的约束; 按类型名称进行比较不是唯一允许的行为,其他实现可能会执行其他操作.这不是一件值得信赖的事情.

  • @Cuadue:啊,这是一个_different_微妙,没有记录,我希望不会出现.被比较的名称实际上不是您从`__name__`属性中看到的名称,这可能就是这里发生的事情.说实话,我不能保证不查找源.这里可能很有意思...... (2认同)
  • 我认为实现回退代码的是[`default_3way_compare`](http://hg.python.org/cpython/file/2.7/Objects/object.c#l762).而且有点令人惊讶:不通过`PyNumber_Check`的对象使用其类型对象的`tp_name`槽...但是_do_的对象都被视为具有名称`""`的对象.(如果_both_是数字,则它们将通过类型对象的id进行比较.这也适用于具有相同名称的两种不同类型.) (2认同)
  • 我编辑了答案,添加了文档的链接(它给出了"按类型名称"规则)和源代码(表明它并未完全遵循); 希望任何对完整细节感兴趣的人都会阅读评论.可能值得将整个比较过程(由CPython 2.7实现)从特殊属性查找写入回退中的同名类型回退作为伪代码,以便那些不想跟踪源代码的人......但是我我太懒了...... (2认同)
  • 这里还有另一个转折点.它会经历与文档相同的后备,就像两个用户定义的类一样(参见[此处](http://pastebin.com/xzMKt1af)查看显示顺序的一些代码),除了` int .__ cmp__`存在并引发一个`TypeError`-它会作为用户定义的(新式)类的异常传播,但对于内置它仍然像在Python 1.5中一样工作,这意味着它回退到默认值 - 比较代码. (2认同)