привязка аргумента для динамического метода __init_subclass__ - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь заставить декоратор класса работать. Декоратор добавит метод __init_subclass__ к классу, к которому он применяется.

Однако, когда метод добавляется в класс динамически, первый аргумент не привязывается к объекту дочернего класса. Почему это происходит?

Как пример: это работает, и статический код ниже - пример того, что я пытаюсь закончить:

class C1:
    def __init_subclass__(subcls, *args, **kwargs):
        super().__init_subclass__(*args, **kwargs)
        print(f"init_subclass -> {subcls.__name__}, {args!r}, {kwargs!r}")

Тест:

>>> D = type("D", (C1,), {})
init_subclass -> D, (), {}

Однако, если я добавлю метод __init__subclass__ динамически, дочерний класс не будет привязан к первому аргументу:

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

Тест:

>>> D = type("D", (C2,), {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: init_subclass() missing 1 required positional argument: 'subcls'

Почему это происходит и как я могу это сделать и заставить привязку работать правильно?

1 Ответ

0 голосов
/ 02 мая 2018

__init_subclass__ является неявным методом класса .

Может быть невозможно использовать супер-аргумент с нулевым аргументом (читайте здесь , если вы хотите узнать почему), но вы должны иметь возможность явно связать супер внутри самого декоратора.

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
...