2010-08-14 11 views
6

Estaba mirando un fragmento del código Python que produje, que, aunque correcto, es feo. ¿Hay una manera más pitonica de hacer esto?Forma pitónica de repetir una llamada a un método en diferentes argumentos finitos

r = self.get_pixel(x,y, RED) 
    g = self.get_pixel(x,y, GREEN) 
    b = self.get_pixel(x,y, BLUE) 
    t = function(r,g,b) 
    if t: 
     r2, g2, b2 = t 
     self.set_pixel(x,y,RED, r2) 
     self.set_pixel(x,y,GREEN, g2) 
     self.set_pixel(x,y,BLUE, b2) 

El problema es la repetición del método exige get_pixel y set_pixel. Para su información:

RED, GREEN, BLUE = range(3) 

También tenga en cuenta que me gustaría preservar la claridad y la limpieza del código.

Respuesta

1

Para llamar a una función con diferentes argumentos y recoger los resultados se puede utilizar una lista por comprensión:

r1, r2, r3 = [foo(x) for x in [x1, x2, x3]] 

llamar a una función de sus efectos secundarios te recomiendo no usar una lista por comprensión y en lugar de utilizar un ordinario para el bucle:

ijs = [(i1, j1), (i2, j2), (i3, j3)] 
for i, j in ijs: 
    bar(i, j) 

sin embargo el problema realmente no es que no debe llamar a su conjunto de píxeles para cada color por separado. Si es posible, cambie su API para que pueda hacer esto según lo sugerido por John Machin:

old_colors = self.get_pixel_colors(x, y) 
new_colors = function(*old_colors) 
if new_colors: 
    self.set_pixel_colors(x, y, *new_colors) 
+3

-1 Esta es la simple adición de soluciones feos a una API feo. Es el tiempo de rediseño de la API: mira la respuesta de @Muhammad Alkarouri, o la mía. –

+0

@John Machin: Lo siento, debería haberlo mencionado. Mi plan era primero dar una respuesta específica a la pregunta exacta y luego manejar el panorama completo y explicar los enfoques alternativos. Pero mientras escribía la primera parte, otros ya me vencieron en la segunda parte.No solo quería duplicar la misma información exacta que otros ya habían publicado en mi publicación, así que simplemente la dejé como estaba, ya que nadie más respondió la pregunta. Ahora veo que mi respuesta fue aceptada y no puedo borrar mi respuesta. Así que he incluido tu respuesta en mi publicación. ¿Eso esta bien? ¿O qué sugieres que debería hacer? –

+0

Yo diría por el patrón de votos que su referencia a la otra respuesta está funcionando o no, por lo que no creo que deba preocuparse ahora. Y gracias por mencionarme como "otros que me ganaron" :) –

1
colors = (RED, GREEN, BLUE) 

r, g, b = [self.get_pixel(x, y, col) for col in colors] 
t = function(r, g, b) 
for col, rgb in zip(colors, t): 
    self.set_pixel(x, y, col, rgb) 
4

me gustaría utilizar una tupla nombrado para representar el color y cambiar la clase a utilizar el color atributos en lugar de individual get_pixel(x,y,c). Por ejemplo:

from collections import namedtuple 
Color = namedtuple('Color', 'red green blue') 
#... 

color = self.get_pixel(x, y) 
t = function(*color) 
if t: 
    self.set_pixel(x, y, color) 

Editar: gracias a John Machin para las correcciones sugeridas aquí. Su respuesta también da más información sobre las razones de este enfoque. Yo agregaría que un namedtuple tiene la ventaja de tener campos como color.red, color.green, color.blue que me gustaría tener disponibles. YMMV.

+0

Esto requiere cambiar las args de 'function' (que no puede ser 'owned' por el OP), o escribir' t = function (* color) '. –

+0

@John Machin: bastante bien. Olvidé el '*', que es la razón por la que usé una tupla en primer lugar. Acabo de editar la respuesta para corregirlo. –

+0

y la última línea debe ser 'self.set_pixel (x, y, color)' –

5

Como está usando self, parece que get_pixel etc. son métodos de su clase. En lugar de listas de comprensión y zip() y otras soluciones, mira las API y corrígelas. Dos sugerencias:

  1. Escribe otro método get_pixel_colors(x, y) que devuelve una 3-tupla. A continuación, puede escribir r, g, b = self.get_pixel_colors(x, y)
  2. mismo modo: self.set_pixel_colors(x, y, r, g, b)

Aún mejor, puede utilizar la notación *args:

old_colors = self.get_pixel_colors(x, y) 
new_colors = function(*old_colors) 
if new_colors: 
    self.set_pixel_colors(x, y, *new_colors) 
Cuestiones relacionadas