<p>您对<code>super</code>的使用无效;它应该被传递它被调用的类的类型(例如,它在中定义的类)和它被传递的实际类型(它被调用的类),所以<code>super(cls, cls)</code>是谎言;显式使用描述符协议函数<code>__get__</code>将其预先绑定到<code>A</code>(在<code>B</code>上调用时绕过描述符协议),因此它总是说“我是从<code>A</code>调用的,带有<code>A</code>”,即使它实际上是在其他对象上调用的</p>
<p>你想要的东西不容易用正确的方法去做<a href="https://stackoverflow.com/a/65206993/364696">your approach of making it a ^{<cd8>} (which means it actually gets ^{<cd5>}, not ^{<cd4>}, as expected) and calling ^{<cd11>}</a>仍然是错误的,即使它碰巧在这里工作。您告诉<code>super</code>遍历<code>None</code>对象的MRO,并调用它在MRO中<code>B</code>之后找到的第一个<code>__init_subclass__</code>。显然,即使<code>B</code>不在MRO中(这应该是一个错误)<a href="https://docs.python.org/3/library/functions.html#super" rel="nofollow noreferrer">according to the docs</a>:“如果第二个参数是一个对象,<code>isinstance(obj, type)</code>必须是真的。如果第二个参数是一个类型,<code>issubclass(type2, type)</code>必须是真的。“这是人生”,它会静静地返回<code>object.__init_subclass__</code>并调用它;它之所以有效,是因为<code>object.__init_subclass__</code>不做任何事情,也不反对被调用</p>
<p>正确执行此操作的唯一方法是为每个要修补的类制作一个新版本的<code>_patched_initsubclass</code>,该类知道它正在修补哪个类。另外,在执行此操作时,通过将<code>__class__</code>放在新方法的闭包范围内,您可以以启用零arg<code>super()</code>的方式进行闭包(零arg<code>super()</code>魔法是由编译器实现的,编译器使类中定义的所有函数在闭包范围内引用<code>__class__</code>或<code>super</code>实际具有<code>__class__</code>可见的闭包). </p>
<p>一个例子是:</p>
<pre><code>def make_patched_initsubclass_for(__class__): # Receive class to patch as __class__ directly
# Same as before, just defined inside function to get closure scope,
# and super() is called with no arguments
def _patched_initsubclass(cls, **kwargs):
print(f"CLS from subclassing A: {cls}")
super().__init_subclass__(**kwargs) # super() roughly equivalent to super(__class__, cls)
# Returns a classmethod so it descriptor protocol
# knows to provide class uniformly, never an instance
return classmethod(_patched_initsubclass)
class A: ...
A.__init_subclass__ = make_patched_initsubclass_for(A) # Produces valid closure for binding to A
class B(A): ... # Output CLS from subclassing A: <class '__main__.B'>
</code></pre>
<p>如果您没有将参数命名为<code>make_patched_initsubclass_for</code>{<cd23>}(命名为<code>patched_cls</code>或类似的名称),则必须使用<code>super(patched_cls, cls)</code>而不是<code>super()</code>,但这两种方式都可以</p>