- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在修补自定义类时遇到问题'__init_subclass__
.我认为这与我将修补函数绑定(bind)到类的方式有关:
def _patched_initsubclass(cls, **kwargs):
print(f"CLS from subclassing A: {cls}")
super(cls, cls).__init_subclass__(**kwargs)
class A: ...
A.__init_subclass__ = _patched_initsubclass.__get__(A, A)
class B(A): ... # Output: CLS from subclassing A: <class '__main__.A'>
但是,我知道正确设置
__init_subclass__
应该有不同的输出:
class F:
def __init_subclass__(cls, **kwargs):
print(f"CLS from subclassing F: {cls}")
pass
class C(F): ... # Output: CLS from subclassing F: <class '__main__.C'>
即
cls
在 super 类里'
__init_subclass__
子类化时定义应该是子类。我试图通过不同的 SO 帖子以及
docs 找到绑定(bind) dunder 方法的正确方法。 ,但一直没有找到正确的方法来做到这一点。
最佳答案
您对 super
的使用是无效的;它应该被传递给它被调用的类的类型(例如它被定义的类)和它被传递的实际类型(它被调用的类),所以 super(cls, cls)
在撒谎;您对描述符协议(protocol)函数的显式使用__get__
预绑定(bind)到 A
(在 B
上调用它时绕过描述符协议(protocol)),所以它总是说“我正在从 A
调用 A
”,即使它实际上是在其他东西上调用的。
你想要的并不容易以正确的方式去做; your approach of making it a classmethod
(which means it actually gets B
, not A
, as expected) and calling super(cls, None)
, 仍然是错误的,即使它碰巧在这里起作用。你在告诉 super
遍历 None
的 MRO对象并调用第一个 __init_subclass__
它在 B
之后找到在 MRO 中。显然,即使 B
不在 MRO 中(应该是错误 according to the docs :“如果第二个参数是对象,isinstance(obj, type)
必须为真。如果第二个参数是类型,issubclass(type2, type)
必须为真。”;c 'est la vie),它默默地返回 object.__init_subclass__
并称它为;它之所以有效,是因为 object.__init_subclass__
什么都不做,也不反对被叫。
正确执行此操作的唯一方法是制作 _patched_initsubclass
的新版本。对于每个要修补的类,都知道它正在修补哪个类。奖励,在执行此操作时,您可以以启用零参数 super()
的方式进行闭包通过把 __class__
在新方法的闭包范围内(零参数 super()
魔术是由编译器完成的,它使引用 __class__
或 super
的类中定义的所有函数实际上以 __class__
闭包在闭包范围内可见)。
一个示例解决方案是:
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'>
如果您没有将参数命名为
make_patched_initsubclass_for
__class__
(命名为
patched_cls
或类似名称),您必须使用
super(patched_cls, cls)
而不是
super()
,但无论哪种方式都可以。
关于python - 修补 __init_subclass__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65205205/
我在修补自定义类时遇到问题'__init_subclass__ .我认为这与我将修补函数绑定(bind)到类的方式有关: def _patched_initsubclass(cls, **kwargs
我四处寻找这个问题的答案,但找不到任何东西。如果之前有人问过这个问题,我深表歉意。 我知道有 3-4 种方法可以从父类强制执行子类的给定方法(编辑元类的 __new__ 方法,挂接到 builtins
我终于升级了我的 python 版本,并且发现了添加的新功能。除其他外,我对新的 __init_subclass__ 摸不着头脑。方法。来自文档: This method is called when
对于在子类上强制执行某些不变量的元类或 __init_subclass__ 应该引发什么异常,是否有任何好的约定? 对于这个答案,我会接受来自 Python 内置行为、PEP、标准库或完善的第三方库的
我想创建一个设置注册表。我还希望能够将设置分组到宏类别中。 以下简化示例适用于单个注册表: class RegistryHolder: registry = {} def __init
我在一个项目中使用 init_subclass ,当我遇到内置方法时有点犹豫,当代码第一次在解释器中运行时启动——没有通过实例化直接引用包含类或它枚举的子类。 谁能告诉我这是怎么回事,并指出任何安全使
我正在尝试让类装饰器工作。装饰器将向其所应用的类添加一个 __init_subclass__ 方法。 但是,当该方法动态添加到类中时,第一个参数不会绑定(bind)到子类对象。为什么会发生这种情况?
使用 type() 创建动态类时,如何将值传递给 __init__subclass__() 中的 kwargs 参数 class Base(): def __init_subclass__(c
我正在尝试编写一个简单的插件系统。 a)为此,我使用 3.6 魔术函数 __init_subclass__ https://stackoverflow.com/a/41924331/1506569 找
我注意到我不能以我想要的方式将 __init_subclass__ 与 Django 模型类一起使用。看起来元类在父类的 __init_subclass__ 方法运行时还没有完成子类的创建。虽然我明白
我的问题灵感来自这个 question . 问题在于 3 级类模型 - 终止类(3 级)仅应存储在注册表中,但 2 级是干扰性的并且也已存储,因为它们是 1 级的子类。 我想通过使用元类摆脱 1 级类
我正在尝试创建一个元类,但是当我将它分配给另一个类时,我收到错误 TypeError: __init_subclass__() takes no keyword arguments但我没有实现任何 _
我有以下代码来比较基类的当前(空)所需功能的实现与其子类,子类必须以某种不同的方式实现它们,以便在运行时被认为是可接受的。如果不使用 metaclass=ABCMeta 并在这些基类方法上实现 @ab
这个问题在这里已经有了答案: Why does a classmethod's super need a second argument? (1 个回答) 3年前关闭。 我尝试从 __init_sub
我正在测试一些 pyqt 小部件及其方法,但当我创建一个继承 QLineEdit 类的子类以便在单击鼠标右键时创建上下文菜单时,我一直遇到问题。此类将主窗口作为父窗口。 运行此代码会产生以下输出: T
我正在尝试将 python 3.6 的新 __init_subclass__ 功能 ( PEP 487 ) 与 abc 模块一起使用。它似乎没有用。以下代码: from abc import ABCM
我是一名优秀的程序员,十分优秀!