python里的类没有父类,但是super()指的是什么呢?

m
microsat
楼主 (北美华人网)
请问_UnsupportedGroupCVMixin类没有父类,其中的super()又指的是什么呢?如何debug到super().split(X, y, groups=groups)?
class _UnsupportedGroupCVMixin:   def split(self, X, y=None, groups=None):     if groups is not None:       warnings.warn(         f"The groups parameter is ignored by {self.__class__.__name__}",         UserWarning,       )     return super().split(X, y, groups=groups)
l
lnghng
这种问题去问AI就行了。
f
fridec2
python 支持 multiple inheritance,你要查查主要的inheritance 是从哪来的,mixin 通常只提供一些附加的功能
比如对于下面的 ‘LeaveOneOut’,主要的 inheritance 来自 BaseCrossValidator: class LeaveOneOut(_UnsupportedGroupCVMixin, BaseCrossValidator):
https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/model_selection/_split.py#L171
F
FengChuQiShan
chatgpt的回答:
super() 是用于调用父类(或基类)的方法的一个内置函数。然而,在你的代码中,_UnsupportedGroupCVMixin 类并没有直接继承任何父类,所以使用 super() 可能会让人感到困惑。 为什么 super() 可以使用 在 Python 中,即使一个类没有显式地继承自另一个类,它默认会继承自 object。所以 super() 实际上是在调用 object 类的方法。然而,object 类本身并没有 split 方法,因此在这种情况下,super().split(X, y, groups=groups) 可能是无效的。 super().split(X, y, groups=groups) 的可能性 通常,这种代码的意图是 _UnsupportedGroupCVMixin 可能会与其他类组合使用(例如通过多重继承),并且希望通过 super() 调用链中的下一个类的方法。如果 _UnsupportedGroupCVMixin 类被用作多重继承中的一个“mixin”类,它并不是最终负责 split 方法实现的那个类,而是希望将调用传递给其他更具体的类。 如何 debug 到 super().split(X, y, groups=groups) 检查继承关系:首先,检查 _UnsupportedGroupCVMixin 类是否真的和其他类组合在一起使用,尤其是哪些类会实际提供 split 方法。 查看 MRO(方法解析顺序):你可以通过 类名.__mro__ 或 类名.mro() 来查看类的 MRO 列表,这将显示在当前类的 super() 调用链中,下一个会被调用的类。 python Copy code print(_UnsupportedGroupCVMixin.__mro__) 设置断点:如果你在调试环境中,可以在 super().split 调用之前设置一个断点,然后单步执行(step into)查看实际调用了哪个类的方法。 总结 super().split(X, y, groups=groups) 的行为取决于 _UnsupportedGroupCVMixin 的继承链。如果 _UnsupportedGroupCVMixin 是在多重继承环境下使用的,那么 super() 会调用继承链中下一个定义了 split 方法的类。如果没有其他类定义 split 方法,代码可能会引发一个 AttributeError。
m
microsat
python 支持 multiple inheritance,你要查查主要的inheritance 是从哪来的,mixin 通常只提供一些附加的功能
比如对于下面的 ‘LeaveOneOut’,主要的 inheritance 来自 BaseCrossValidator: class LeaveOneOut(_UnsupportedGroupCVMixin, BaseCrossValidator):
https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/model_selection/_split.py#L171

fridec2 发表于 2024-08-26 12:01

谢谢!
当我们使用LeaveOneOut的时候,用什么调试器能跟踪到 LeaveOneOut.split()
进而,再跟踪到_UnsupportedGroupCVMixin.split(), 或者 BaseCrossValidator.split()?
_UnsupportedGroupCVMixin作为父类是排在第一位,为什么LeaveOneOut.split() 不是来自_UnsupportedGroupCVMixin.split() 而是来自BaseCrossValidator.split()?
我的pycharm的debug跟踪器,跟踪到的是_UnsupportedGroupCVMixin.split(),而不是BaseCrossValidator.split()。
但是我的pycharm的debug跟踪器,跟踪到_UnsupportedGroupCVMixin.split()里的最后一句 super().split(X, y, groups=groups)
就再也无法继续跟踪了.
也就是说super()指的是哪个类,跟踪不到了。
大家有什么高级的python debug器,能跟踪进sklearn的内核?
m
microsat
FengChuQiShan 发表于 2024-08-26 12:13
chatgpt的回答:
super() 是用于调用父类(或基类)的方法的一个内置函数。然而,在你的代码中,_UnsupportedGroupCVMixin 类并没有直接继承任何父类,所以使用 super() 可能会让人感到困惑。 为什么 super() 可以使用 在 Python 中,即使一个类没有显式地继承自另一个类,它默认会继承自 object。所以 super() 实际上是在调用 object 类的方法。然而,object 类本身并没有 split 方法,因此在这种情况下,super().split(X, y, groups=groups) 可能是无效的。 super().split(X, y, groups=groups) 的可能性 通常,这种代码的意图是 _UnsupportedGroupCVMixin 可能会与其他类组合使用(例如通过多重继承),并且希望通过 super() 调用链中的下一个类的方法。如果 _UnsupportedGroupCVMixin 类被用作多重继承中的一个“mixin”类,它并不是最终负责 split 方法实现的那个类,而是希望将调用传递给其他更具体的类。 如何 debug 到 super().split(X, y, groups=groups) 检查继承关系:首先,检查 _UnsupportedGroupCVMixin 类是否真的和其他类组合在一起使用,尤其是哪些类会实际提供 split 方法。 查看 MRO(方法解析顺序):你可以通过 类名.__mro__ 或 类名.mro() 来查看类的 MRO 列表,这将显示在当前类的 super() 调用链中,下一个会被调用的类。 python Copy code print(_UnsupportedGroupCVMixin.__mro__) 设置断点:如果你在调试环境中,可以在 super().split 调用之前设置一个断点,然后单步执行(step into)查看实际调用了哪个类的方法。 总结 super().split(X, y, groups=groups) 的行为取决于 _UnsupportedGroupCVMixin 的继承链。如果 _UnsupportedGroupCVMixin 是在多重继承环境下使用的,那么 super() 会调用继承链中下一个定义了 split 方法的类。如果没有其他类定义 split 方法,代码可能会引发一个 AttributeError。

你这个例子,说明chatgpt就是个笨蛋。除了炒作泡沫。啥也不会。
f
fridec2
回复 5楼 microsat 的帖子
> _UnsupportedGroupCVMixin作为父类是排在第一位,为什么LeaveOneOut.split() 不是来自_UnsupportedGroupCVMixin.split() 而是来自BaseCrossValidator.split()?
LeaveOneOut.split() 是来自 _UnsupportedGroupCVMixin.split(),然后这个 object 的 super().split() 是来自 另一个父类, BaseCrossValidator.split()。这个解析是因为 python 的 MRO :https://www.geeksforgeeks.org/multiple-inheritance-in-python/
调试的话,试试用最基本的 pdb。
import pdb pdb.set_trace()
比如对于geeksforgeeks里的例子,每个 super() 都能访问到
#!/usr/bin/env python3
class A:   def __init__(self):     print("Initializing A")
class B(A):   def __init__(self):     super().__init__()     print("Initializing B")
class C(A):   def __init__(self):     super().__init__()     print("Initializing C")
class D(B, C):   def __init__(self):     super().__init__()     print("Initializing D")
import pdb pdb.set_trace() d = D()
结果是
Initializing A Initializing C Initializing B Initializing D
m
microsat
回复 7楼 fridec2 的帖子
多谢!
LeaveOneOut 有两个父类,第一个父类是 _UnsupportedGroupCVMixin。第二个父类是BaseCrossValidator。
_UnsupportedGroupCVMixin里的super().split() 为什么不是_UnsupportedGroupCVMixin的父类的split(),
而是_UnsupportedGroupCVMixin的兄弟(也就是BaseCrossValidator)的split()?
m
microsat
fridec2 发表于 2024-08-26 17:09
回复 5楼 microsat 的帖子
> _UnsupportedGroupCVMixin作为父类是排在第一位,为什么LeaveOneOut.split() 不是来自_UnsupportedGroupCVMixin.split() 而是来自BaseCrossValidator.split()?
LeaveOneOut.split() 是来自 _UnsupportedGroupCVMixin.split(),然后这个 object 的 super().split() 是来自 另一个父类, BaseCrossValidator.split()。这个解析是因为 python 的 MRO :https://www.geeksforgeeks.org/multiple-inheritance-in-python/
调试的话,试试用最基本的 pdb。
import pdb pdb.set_trace()
比如对于geeksforgeeks里的例子,每个 super() 都能访问到
#!/usr/bin/env python3
class A:   def __init__(self):     print("Initializing A")
class B(A):   def __init__(self):     super().__init__()     print("Initializing B")
class C(A):   def __init__(self):     super().__init__()     print("Initializing C")
class D(B, C):   def __init__(self):     super().__init__()     print("Initializing D")
import pdb pdb.set_trace() d = D()
结果是
Initializing A Initializing C Initializing B Initializing D

你给的这个例子,真有学习的价值。
f
fridec2
microsat 发表于 2024-08-26 18:09
回复 7楼 fridec2 的帖子
多谢!
LeaveOneOut 有两个父类,第一个父类是 _UnsupportedGroupCVMixin。第二个父类是BaseCrossValidator。
_UnsupportedGroupCVMixin里的super().split() 为什么不是_UnsupportedGroupCVMixin的父类的split(),
而是_UnsupportedGroupCVMixin的兄弟(也就是BaseCrossValidator)的split()?

这是由 python 的 MRO 顺序决定的
LeaveOneOut 的 MRO 是 【LeaveOneOut,_UnsupportedGroupCVMixin,BaseCrossValidator, object】
按这个顺序,_UnsupportedGroupCVMixin 的父类是 BaseCrossValidator
MRO 的算法: https://en.wikipedia.org/wiki/C3_linearization https://www.geeksforgeeks.org/method-resolution-order-in-python-inheritance/




g
gokgs
唉, 真马工, 假马工, 都不要在这问 coding 问题好不?
自己 google 一下就差不多了。
f
fridec2
回复 9楼 microsat 的帖子
是挺奇怪的,稍微改改(改了两行),结果如下
#!/usr/bin/env python3
class A:  def __init__(self):   super().__init__()   print("Initializing A")
class B(A):  def __init__(self):   super().__init__()   print("Initializing B")
class C():  def __init__(self):   super().__init__()   print("Initializing C")
class D(B, C):  def __init__(self):   super().__init__()   print("Initializing D")
d = D()
Initializing C Initializing A Initializing B Initializing D
f
fridec2
回复 11楼 gokgs 的帖子
最后再贴一个变种
#!/usr/bin/env python3
class A:  def __init__(self):   print("Initializing A")
class B(A):  def __init__(self):   super().__init__()   print("Initializing B")
class C():  def __init__(self):   super().__init__()   print("Initializing C")
class D(B, C):  def __init__(self):   super().__init__()   print("Initializing D")
d = D()
Initializing A Initializing B Initializing D
m
microsat
fridec2 发表于 2024-08-26 21:40
这是由 python 的 MRO 顺序决定的
LeaveOneOut 的 MRO 是 【LeaveOneOut,_UnsupportedGroupCVMixin,BaseCrossValidator, object】
按这个顺序,_UnsupportedGroupCVMixin 的父类是 BaseCrossValidator
MRO 的算法: https://en.wikipedia.org/wiki/C3_linearization https://www.geeksforgeeks.org/method-resolution-order-in-python-inheritance/





多谢!