argument binding for dynamic __init_subclass__ method
我正在努力让一个班级的装饰工工作。decorator将向应用它的类添加一个
但是,当动态地将方法添加到类中时,第一个参数没有绑定到子类对象。为什么会这样?
举个例子:这是可行的,下面的静态代码是一个例子,说明了我最后要做的事情:
1 2 3 4 | class C1: def __init_subclass__(subcls, *args, **kwargs): super().__init_subclass__(*args, **kwargs) print(f"init_subclass -> {subcls.__name__}, {args!r}, {kwargs!r}") |
测试:
1 2 | >>> D = type("D", (C1,), {}) init_subclass -> D, (), {} |
但是,如果动态添加
1 2 3 4 5 6 7 8 9 10 11 | def init_subclass(subcls, **kwargs): super().__init_subclass__(**kwargs) print(f"init_subclass -> {subcls.__name__}, {args!r}, {kwargs!r}") def decorator(Cls): Cls.__init_subclass__ = init_subclass return Cls @decorator class C2: pass |
测试:
1 2 3 4 | >>> D = type("D", (C2,), {}) Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: init_subclass() missing 1 required positional argument: 'subcls' |
为什么会发生这种情况?我如何才能做到这一点并使绑定以正确的方式工作?
可能不可能使用零参数super(如果您想了解原因,请阅读此处),但是您应该能够显式地将super绑定到装饰器本身中。
1 2 3 4 5 6 7 8 9 10 11 12 13 | def decorator(Cls): def __init_subclass__(subcls, **kwargs): print(f'init subclass {Cls!r}, {subcls!r}, {kwargs!r}') super(Cls, subcls).__init_subclass__(**kwargs) Cls.__init_subclass__ = classmethod(__init_subclass__) return Cls @decorator class C: pass class D(C): pass |