Python3 - using super() in __eq__ methods raises RuntimeError: super(): __class__ cell not found
Python3 - using super() in __eq__ methods raises RuntimeError: super(): __class__ cell not found
我正在修补 class 的 __eq__
方法。我发现以下工作:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return object.__eq__(obj, other)
这不起作用:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(other)
这有时有效,但有时会引发错误:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(self, other)
错误:
<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
你能解释一下这是怎么回事吗?如何将 object
正确替换为 super()
?
您不能在 class 之外定义的函数中使用不带参数的 super()
。 __class__
单元 super()
所依赖的仅提供给 class
主体中定义的函数。来自 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.
使用双参数形式,明确命名 class:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super(ClassYouPutThisOn, obj).__eq__(other)
ClassYouPutThisOn.__eq__ = eq
这需要您在 monkey 补丁中明确命名 class,从而降低其重用性。
相反,您可以通过将 eq
嵌套在另一个以 __class__
作为本地名称的函数中,手动 提供所需的 __class__
单元格 :
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()
通过从调用帧中获取第一个本地名称(即传递给函数调用的第一个参数,通常称为 self
)找到第二个参数(对实例的引用) .
另见 Why is Python 3.x's super() magic?
使用嵌套函数方法的演示:
>>> 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
我正在修补 class 的 __eq__
方法。我发现以下工作:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return object.__eq__(obj, other)
这不起作用:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(other)
这有时有效,但有时会引发错误:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(self, other)
错误:
<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
你能解释一下这是怎么回事吗?如何将 object
正确替换为 super()
?
您不能在 class 之外定义的函数中使用不带参数的 super()
。 __class__
单元 super()
所依赖的仅提供给 class
主体中定义的函数。来自 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.
使用双参数形式,明确命名 class:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super(ClassYouPutThisOn, obj).__eq__(other)
ClassYouPutThisOn.__eq__ = eq
这需要您在 monkey 补丁中明确命名 class,从而降低其重用性。
相反,您可以通过将 eq
嵌套在另一个以 __class__
作为本地名称的函数中,手动 提供所需的 __class__
单元格 :
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()
通过从调用帧中获取第一个本地名称(即传递给函数调用的第一个参数,通常称为 self
)找到第二个参数(对实例的引用) .
另见 Why is Python 3.x's super() magic?
使用嵌套函数方法的演示:
>>> 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