2013-05-18 12 views
25

próbuję zdefiniować kilka metod klasy przy użyciu innej metody klasy bardziej ogólny sposób następujący:functools.partial na metody klasy

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

Ale gdy próbuję wywołać żadnej z tych metod uzyskać:

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

Domyślam się, że self nie jest przekazywane do _color od rgb.red(rgb) działa.

Odpowiedz

30

Tworzysz częściowe na funkcji, a nie metody. functools.partial() obiekty nie są deskryptorami, same nie dodadzą argumentu self i nie będą mogły same działać. Możesz łączyć ze sobą metody lub funkcje związane z wrapem, ale nie działają one w ogóle z niezwiązanymi metodami. To documented:

partial obiekty są jak function obiektów, które są wymagalne, słaby referencable i może mieć atrybuty. Jest kilka ważnych różnic. Na przykład atrybuty __name__ i __doc__ nie są tworzone automatycznie. Ponadto obiekty zdefiniowane w klasach zachowują się jak statyczne metody i nie przekształcają się w powiązane metody podczas wyszukiwania atrybutów instancji.

Zamiast tego należy użyć property; te deskryptory:

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

Jak Pythona 3.4, można użyć nowego functools.partialmethod() object tutaj; będzie to zrobić dobry uczynek, gdy związany z wystąpieniem:

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

ale these'd trzeba nazwać, podczas gdy property obiekty mogą być wykorzystane jako atrybutów prostych.

+0

Rozumiem. Dzięki. – Arjor

+1

Co z 'self.red = functools.partial (RGB._color, self, 'red')' w '__init__'? Jest kompatybilny z Python2. – dashesy

+2

@dashesy: ​​jasne, ale powoduje to umieszczenie tych obiektów na każdej instancji (koszt pamięci), co również utrudnia zastąpienie ich przez podklasę. –

Powiązane problemy