【问题标题】:Equality operator for functions?函数的等式运算符?
【发布时间】:2021-03-21 22:37:49
【问题描述】:

我正在加深对 Python 的理解,最近我了解到函数必须是类(?),并且 def func(): 只是实例化了 function 类的对象。老实说,当我创建func 的属性时,我大吃一惊。

潜伏在dir(func) 中发现.__eq__ 等特殊方法确实都是继承的,想玩弄一下:

def func(n):
    print(n)
    def __eq__(self,func2):
        print('hello')

但是,它不起作用:

>>> func.__eq__(print)
NotImplemented

为函数重载相等运算符的正确方法是什么?如果没有正确的 class 定义,我看不到如何重载它。

【问题讨论】:

  • “最近我明白函数必须是类” - 我不知道你是如何或从哪里得到这个想法的,但这是错误的。函数是类的实例,就像任何其他 Python 对象(包括类本身)一样,但函数不是类。
  • 谢谢你们,你们其实都是对的,我明白发生了什么。我尝试的是import typesdef equality_mine(): 我自己的新相等运算符,以及types.FunctionType.__eq__ = equality_mine 使用它来重载函数相等运算符:TypeError: can't set attributes of built-in/extension type 'function'。我想有人在我之前考虑过。
  • 您可以通过在其中定义__call__() 特殊方法来创建自己的类,其实例可调用。这样的类可以有自己的__eq__() 比较方法,就像其他类一样。你甚至可以“注册”你的类,这样对isinstance() 的调用就会认为它的实例与types.FunctionType 的实例相同。换句话说,您自己的类的实例(几乎)“在功能上”等同于内置函数。 ;¬)
  • 我认为您的意思是“覆盖”而不是“重载”

标签: python function class comparison-operators


【解决方案1】:

由于 python 将所有函数都视为对象,因此可能值得考虑将创建函数视为创建类 function(未记录)的实例,其中 __call__ 方法是使用 @ 创建的函数的主体987654324@。如果您想了解实现细节,function 类的实际 C 源代码是 on Github

返回 NotImplemented:

在 Python 中,如果对象不覆盖 __eq____hash__,则有默认实现,其中 __hash__ = builtins.id__eq__ 类似于 lambda self, other: self is other。当比较运算符返回 NotImplemented 时,这会指示运行时搜索执行相同操作的另一个方法,例如尝试使用 __ne__ 而不是 __eq__,或者尝试来自父级的运算符。

>>> def test(a):
...     return a
...
>>> def test2(a):
...     return a
...
>>> test == test2
False
>>> test.__eq__(test2)
NotImplemented

您还可以通过创建一个不覆盖 __eq__ 的虚拟类来测试这一点(就像 function 类不覆盖一样):

>>> class testcls:
...     pass
... 
>>> t1 = testcls()
>>> t2 = testcls()
>>> t1.__eq__(t2)
NotImplemented
>>> t1.__eq__(t1)
True
>>> t1 == t2
False

【讨论】:

    【解决方案2】:

    不,实际上,函数不必是类(但它们在 Python 中)。但那是另一回事了。

    您似乎误解了__eq__ 是一种方法,即您需要它所属的class 才能重载它。您的代码所做的是在另一个函数中定义一些自定义函数,这是有效的 Python 代码,但与 __eq__ 重载无关。

    由于你不能继承函数,你不能覆盖它的eq。即使你能做到这一点,由于一些纯粹的理论原因,它也行不通。

    【讨论】:

    • 函数不是 Python 中的类,它们是内置 types.FunctionType实例
    • @martineau thx,不知道。但是 lambda 是类,对吧?
    • 不,lambda 函数是内置 types.LambdaType 的实例。您可以为自己see
    • (并且types.LambdaTypetypes.FunctionType 是同一类型。它被列在两个名称下,因为Guido(或其他一些核心开发人员)不确定它们是否总是同一类型。 )
    猜你喜欢
    • 2010-11-05
    • 1970-01-01
    • 2018-08-29
    • 2015-01-05
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多