Как динамически назначать методы класса изнутри класса? - PullRequest
0 голосов
/ 21 июня 2020
import util
class C():
    save = util.save
setattr(C, 'load', util.load)

C.save виден линтеру, а C.load - нет. Таким образом, существует некоторая разница между назначением методов класса изнутри самого класса и извне. То же самое и для разработчиков документации; например, Sphinx не подтвердит :meth:C.load - вместо этого нужно сделать :func:util.load, что вводит в заблуждение, если load должен быть методом C. IDE (Spyder) также не может выполнить метод «go to» с помощью кода self.load.

Конечная цель - заставить линтер (+ docs & IDE) распознавать load как C ' s, как и C.save, но назначение метода класса должно быть динамическим c ( контекст ). Можно ли это сделать?


Примечание : назначение Dynami c состоит в том, чтобы автоматически извлекать методы из модулей (например, util) вместо того, чтобы обновлять вручную C при добавлении / удалении метода.

1 Ответ

0 голосов
/ 21 июня 2020

Заявление об ограничении ответственности : Это решение не работает во всех случаях использования, см. Комментарии. Я оставляю его здесь, поскольку он все еще может быть полезен при некоторых обстоятельствах.

Я не знаю о линтере и Sphinx, но IDE, такая как PyCharm, распознает метод, если вы объявите его заранее, используя подсказку типа. В приведенном ниже коде без строки load: Callable[[], None] я получаю предупреждение «Неразрешенная ссылка на атрибут», но со строкой в ​​файле нет предупреждений. См. docs для получения дополнительной информации о подсказках типов.

Примечания:

  • Даже с более общим load: Callable проверка типов удовлетворительна.
  • Если вы не всегда объявляете вызываемый объект, допустимое объявление - load: Optional[Callable] = None. Это означает, что значение по умолчанию - Нет. Если вы затем вызовете его, не задав его, вы получите сообщение об ошибке, но оно у вас уже есть, это не связано с этим набором.

ps У меня нет вашего utils, поэтому я определил некоторые функции в самом файле.

from typing import Callable


def save():
    pass


def load():
    pass


class C:
    load: Callable[[], None]
    save = save


setattr(C, 'load', load)

C.load()
...