Переопределение метода класса в python

Контекст

Я пытаюсь установить некоторые «плагины» (я не уверен, что это правильное определение для этого) к моему коду. Под «плагином» я подразумеваю модуль, который определяет модель (это научный код) таким образом, что его существования достаточно, чтобы использовать его где-либо еще в коде.

Конечно, эти плагины должны следовать шаблону, который использует некоторые модули/функции/классы, определенные в моем коде. Вот небольшой фрагмент соответствующей части моего кода:

# [In the code]
class AllModels():
    def __init__(self):
        """
        Init.
        """
        self.count = 0

    def register(self, name, model):
        """
        Adds a model to the code
        """
        setattr(self, name, model)
        self.count += 1
        return

class Model():
    def __init__(self, **kwargs):
        """
        Some constants that defines a model
        """
        self.a = kwargs.get("a", None)
        self.b = kwargs.get("b", None)
        # and so on...

    def function1(self, *args, **kwargs):
        """
        A function that all models will have, but which needs:
            - to have a default behavior (when the instance is created)
            - to be redefinable by the "plugin" (ie. the model)
        """
        # default code for the default behavior
        return

instance = AllModels()

и вот соответствующая часть «плагина»:

# [in the plugin file]
from code import Model, instance
newmodel = Model(a="a name", b="some other stuff")

def function1(*args, **kwargs):
    """
    Work to do by this model
    """
    # some specific model-dependent work
    return

instance.register(newmodel)

Дополнительная информация и требования

  • function1имеет одинаковую сигнатуру для любой модели плагин, но обычно выполняет разные задачи для каждого.

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

  • В плагине function1могут использоваться некоторые другие функции, определенные только в этом плагине. Я утверждаю это, потому что код работает с многопроцессорным модулем, и мне нужен экземпляр instanceэкземпляра AllModels, чтобы иметь возможность вызывать function1в дочерних процессах. .Экземпляр определен в родительском процессе, а также в подключаемых модулях модели, но будет использоваться в других дочерних процессах (хотя никаких изменений в нем не делается).

  • Было бы здорово, если бы function1при «переопределении» подключаемым модулем могли получить доступ к атрибутам экземпляра Model(т.е. self).

Проблема

Я прочитал много разных источников документации по python и несколько вопросов. Я вижу только два/три возможных решения этой проблемы:

1) не объявлять метод function1в классе Model, а просто установить его как атрибут, когда плагин создает новый экземпляр этого.

# [in the plugin file]
def function1(*args, **kwargs):
    # ....
    return
newmodel.function1 = function1

, а затем вызывать его при необходимости. В этом случае атрибуту function1в объекте Modelбудет присвоено значение None. Одно предостережение заключается в том, что для function1 нет «поведения по умолчанию» (это должно быть обработано в коде, например, тестирование , если instance.function1 равно None: ... ), и еще большая проблема заключается в том, что я не могу получить доступ к selfтаким образом...

2) каким-то образом используя декораторы python. Я никогда не использовал это, и документация, которую я читал, не так проста (я имею в виду не прямолинейна из-за огромного количества возможностей ее использования). Но это кажется хорошим решением. Однако меня беспокоит его влияние на производительность (я читал, что это может замедлить выполнение декорированной функции/метода).Если это решение является лучшим вариантом, то я хотел бы знать, как его использовать (возможно, быстрый фрагмент), и можно ли использовать атрибуты класса Model:

# [in the plugin file]
@mydecorator
def function1(self, *args, **kwargs):
    """
    I'm not sure I can use *self*, but it would be great since some attributes of self are used for some other function similar to *function1*...
    """
    # some stuff using *self*, eg.:
    x = self.var **2 + 3.4
    # where self.var has been defined before, eg.: newmodel.var = 100.

3) используя модуль typesи его MethodType... я не уверен, что это актуально в моем случае... но я могу ошибаться.

Как вы, наверное, поняли после этого длинного вопроса, я не очень хорошо знаком с такими функциями Python, и мое понимание декораторов сейчас очень плохое. Продолжая читать некоторую документацию, я подумал, что, возможно, стоит задать вопрос здесь, поскольку я не уверен в том, в каком направлении нужно двигаться, чтобы решить мою проблему.

Решение

Прелесть ответа Сендерле в том, что он действительно прост и очевиден... И пропустить его - позор. Извините за загрязнение SO этим вопросом.

6
задан mhavel 23 March 2012 в 07:02
поделиться