2013-05-18 12 views
25

sto cercando di definire alcuni metodi della classe utilizzando un altro metodo di classe più generica come segue:functools.partial sul metodo di classe

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

Ma quando tento di richiamare uno qualsiasi di questi metodi ottengo:

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

Immagino che self non venga passato a _color dal rgb.red(rgb) opere.

risposta

30

Si stanno creando i partial sulla funzione , non sul metodo. Gli oggetti functools.partial() non sono descrittori, non aggiungeranno essi stessi l'argomento self e non possono agire da soli come metodi. È possibile solo metodi o funzioni associati al wrap , non funzionano affatto con metodi non associati. Questo è documented:

partial oggetti sono come function oggetti in quanto sono callable, riferibile deboli, e possono avere attributi. Ci sono alcune differenze importanti. Ad esempio, gli attributi __name__ e __doc__ non vengono creati automaticamente. Inoltre, gli oggetti partial definiti nelle classi si comportano come metodi statici e non si trasformano in metodi associati durante la ricerca di attributi dell'istanza.

Utilizzare invece property s; questi sono descrittori:

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

Come di Python 3.4, è possibile utilizzare la nuova functools.partialmethod() object qui; che sarà fare la cosa giusta quando si lega a un'istanza:

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

ma these'd devono essere chiamati, mentre i property oggetti possono essere utilizzati come attributi semplici.

+0

Capito. Grazie. – Arjor

+1

E riguardo 'self.red = functools.partial (RGB._color, self, 'red')' in '__init__'? È anche compatibile con Python2. – dashesy

+2

@dashy: certo, ma mette quegli oggetti su ciascuna istanza (un costo di memoria), rendendo anche più difficile per una sottoclasse di sostituirli. –

Problemi correlati