2013-05-18 2 views
25

Я пытаюсь определить некоторые методы класса с использованием другого метода более общего класса следующим образом: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) 

Я думаю, что сам не перешел на _color с rgb.red(rgb) работает.

ответ

30

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

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

Используйте вместо этого property s; эти являются Дескрипторы:

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() object здесь; он будет делать правильно, когда связанный с экземпляром:

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') 

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

+0

Получил. Благодарю. – Arjor

+1

Что относительно 'self.red = functools.partial (RGB._color, self, 'red')' in '__init__'? Совместимость с Python2 тоже. – dashesy

+2

@ dashesy: ​​конечно, но это помещает эти объекты в каждый экземпляр (стоимость памяти), что также затрудняет замену подкласса. –

Смежные вопросы