Подтвердить что ты не робот

Functools.partial по методу класса

Я пытаюсь определить некоторые методы класса с использованием другого более универсального метода класса следующим образом:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    red = functools.partial(_color, type='_red')
    blue = functools.partial(_color, type='_blue')
    green = functools.partial(_color, type='_green')

Но когда я пытаюсь вызвать любой из этих методов, я получаю:

rgb = RGB(100, 192, 240)
print rgb.red()
TypeError: _color() takes exactly 2 arguments (1 given)

Я думаю, что self не передается в _color, так как rgb.red(rgb) работает.

4b9b3361

Ответ 1

Вы создаете частичные функции, а не метод. functools.partial() объекты не являются дескрипторами, они сами не будут добавлять аргумент self и не могут действовать как сами методы. Вы можете только обернуть связанные методы или функции, они вообще не работают с несвязанными методами. Это документировано:

partial объекты похожи на объекты function, поскольку они являются вызываемыми, слабыми ссылочными и могут иметь атрибуты. Есть некоторые важные отличия. Например, атрибуты __name__ и __doc__ не создаются автоматически. Кроме того, partial объекты, определенные в классах, ведут себя как статические методы и не преобразуются в связанные методы при просмотре атрибутов экземпляра.

Используйте property; это дескрипторы:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    @property
    def red(self): return self._color('_red')
    @property
    def blue(self): return self._color('_blue')
    @property
    def green(self): return self._color('_green')

Как и в случае с Python 3.4, здесь можно использовать новый объект functools.partialmethod(); он будет действовать правильно, если привязан к экземпляру:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    red = functools.partialmethod(_color, type='_red')
    blue = functools.partialmethod(_color, type='_blue')
    green = functools.partialmethod(_color, type='_green')

но они должны быть вызваны, в то время как объекты property могут использоваться как простые атрибуты.