почему функция, присвоенная атрибуту класса, рассматривается как метод экземпляра? - PullRequest
1 голос
/ 26 июня 2019

Я пытаюсь запрограммировать объект, у которого есть метод getCallable(), возвращающий функцию. Я хотел бы предоставить эту функцию в качестве атрибута класса, чтобы я мог просто наследовать свой родительский класс и устанавливать разные функции для каждого дочернего класса.

В моем случае объект представляет собой виджет с интерактивными полями ввода, которые пользователи могут заполнять для установки большинства параметров функций.

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

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

Вот очень упрощенный пример, который воспроизводит мою проблему:

def mult(a, b):
    return a * b


class MultiplierFilter(object):
    function = mult

    def __init__(self):
        super().__init__()
        self.multiplier = 1

    def parameters(self):
        return {
            "multiplier": self.multiplier}

    def setParameters(self, params):
        """
        :param dict params:
        :return:
        """
        self.multiplier = params.get("multiplier", 1)

    def getCallable(self):
        """Return a function that takes a number as only argument and returns
        another number.
        """
        mult = self.multiplier

        def f(value):
            return self.function(value, mult)
        return f


if __name__ == '__main__':
    multiplier_object = MultiplierFilter()
    multiplier_object.setParameters({"multiplier": 2})

    test_function = multiplier_object.getCallable()
    print(test_function(7.))

И сообщение об ошибке:

Traceback (most recent call last):
  File "C:/Users/Pierre/PycharmProjects/pyipsdk_tuto/2.py", line 39, in <module>
    print(test_function(7.))
  File "C:/Users/Pierre/PycharmProjects/pyipsdk_tuto/2.py", line 30, in f
    return self.function(value, mult)
TypeError: mult() takes 2 positional arguments but 3 were given

1 Ответ

3 голосов
/ 26 июня 2019

Неважно, как вы определили функцию; это просто функция в пространстве имен класса в конце определения class, и поэтому она обрабатывается как любая другая функция, которую вы там определили. Блок class - это полностью функциональный код Python, единственное, что имеет значение, это каков результат в конце блока.

То, что вы хотите, это украсить функцию с помощью staticmethod:

class MultiplierFilter:
    function = staticmethod(mult)

Это предотвратит неявную передачу self во время вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...