Python3 - 在 __eq__ 方法中使用 super() 会引发 RuntimeError: super(): __class__ cell not found [英] Python3 - using super() in __eq__ methods raises RuntimeError: super(): __class__ cell not found

查看:147
本文介绍了Python3 - 在 __eq__ 方法中使用 super() 会引发 RuntimeError: super(): __class__ cell not found的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在修补类的 __eq__ 方法.我发现以下有效:

 def eq(obj, other):如果 isinstance(other, str):返回 obj.name.upper() == other.upper()别的:return object.__eq__(obj, other)

这不起作用:

 def eq(obj, other):如果 isinstance(other, str):返回 obj.name.upper() == other.upper()别的:返回 super().__eq__(other)

这有时有效,但有时会引发和错误:

def eq(obj, other):如果 isinstance(other, str):返回 obj.name.upper() == other.upper()别的:返回 super().__eq__(self, other)

错误:

在 eq(obj, 其他)3 返回 obj.name.upper() == other.upper()4 其他:---->5 返回 super().__eq__(self, other)67运行时错误:super():找不到 __class__ 单元格

你能解释一下这里发生了什么吗?如何用 super() 正确替换 object?

解决方案

您不能在类外定义的函数中使用没有参数的 super().__class__ 单元 super() 所依赖的仅提供给 class 主体中定义的函数.来自 super() 文档:

<块引用>

零参数形式仅在类定义中起作用,因为编译器会填写必要的详细信息以正确检索正在定义的类,以及访问普通方法的当前实例.

使用 2 参数形式,明确命名类:

def eq(obj, other):如果 isinstance(other, str):返回 obj.name.upper() == other.upper()别的:return super(ClassYouPutThisOn, obj).__eq__(other)ClassYouPutThisOn.__eq__ = eq

这要求您在猴子补丁中明确命名该类,从而使其不再用于重用.

相反,您可以通过将 eq 嵌套在另一个具有 __class__ 的函数中,手动 提供所需的 __class__ 单元格作为本地名称:

def patch_eq(cls):__class__ = cls # 为 super() 提供闭包单元def eq(obj, 其他):如果 isinstance(other, str):返回 obj.name.upper() == other.upper()别的:返回 super().__eq__(other)cls.__eq__ = eq

super() 通过从调用框架中获取第一个本地名称(即传递给函数调用的第一个参数,通常称为 )来找到第二个参数(对实例的引用)自己).

另请参阅为什么 Python 3.x 的 super() 魔术?

使用嵌套函数方法的演示:

<预><代码>>>>Foo类:... name = 'bar'... def __eq__(self, other):...返回假...>>>Foo() == '酒吧'错误的>>>Foo() == Foo()错误的>>>patch_eq(Foo)>>>Foo() == '酒吧'真的>>>Foo() == Foo()错误的

I am monkey patching the __eq__ method of a class. I found that the following works:

   def eq(obj, other):
       if isinstance(other, str):
          return obj.name.upper() == other.upper()
       else:
          return object.__eq__(obj, other)

This does not work:

  def eq(obj, other):
     if isinstance(other, str):
         return obj.name.upper() == other.upper()
     else:
        return super().__eq__(other)

This sometimes works, but sometimes raises and error:

def eq(obj, other):
   if isinstance(other, str):
       return obj.name.upper() == other.upper()
   else:
       return super().__eq__(self, other)

The error:

<ipython-input-128-91287536205d> in eq(obj, other)
      3         return obj.name.upper() == other.upper()
      4     else:
----> 5         return super().__eq__(self, other)
      6 
      7 

RuntimeError: super(): __class__ cell not found

Can you explain what is going on here? How do I properly replace object with super()?

解决方案

You can't use super() without arguments in a function defined outside of a class. The __class__ cell super() relies on is only provided for functions defined in a class body. From the super() documentation:

The zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.

Use the 2-argument form, naming the class explicitly:

def eq(obj, other):
   if isinstance(other, str):
       return obj.name.upper() == other.upper()
   else:
       return super(ClassYouPutThisOn, obj).__eq__(other)

ClassYouPutThisOn.__eq__ = eq

This requires you to explicitly name the class in the monkey patch, making it less useful for reuse.

Instead, you can provide the required __class__ cell manually by nesting eq in another function with __class__ as a local name:

def patch_eq(cls):
    __class__ = cls  # provide closure cell for super()
    def eq(obj, other):
       if isinstance(other, str):
           return obj.name.upper() == other.upper()
       else:
           return super().__eq__(other)
    cls.__eq__ = eq

super() finds the second argument (reference to the instance), by taking the first local name from the calling frame (i.e. the first parameter passed into the function call, usually called self).

Also see Why is Python 3.x's super() magic?

Demo using the nested-function approach:

>>> class Foo:
...     name = 'bar'
...     def __eq__(self, other):
...         return False
...
>>> Foo() == 'Bar'
False
>>> Foo() == Foo()
False
>>> patch_eq(Foo)
>>> Foo() == 'Bar'
True
>>> Foo() == Foo()
False

这篇关于Python3 - 在 __eq__ 方法中使用 super() 会引发 RuntimeError: super(): __class__ cell not found的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆