2010-08-14 3 views
6

Ich starrte auf ein Stück Python-Code, den ich produzierte, der, obwohl korrekt, hässlich ist. Gibt es eine mehr pythische Art, dies zu tun?Pythonischer Weg, einen Methodenaufruf auf verschiedenen endlichen Argumenten zu wiederholen

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) 

Das Problem ist, die Wiederholung des Verfahrens zur get_pixel aufruft und set_pixel. Zu Ihrer Information:

RED, GREEN, BLUE = range(3) 

Beachten Sie auch, dass ich Code Klarheit und Sauberkeit bewahren möchte.

Antwort

1

Um eine Funktion mit unterschiedlichen Argumenten aufrufen und die Ergebnisse sammeln Sie eine Liste Verständnis verwenden können:

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

So rufen Sie eine Funktion für seine Nebenwirkungen würde ich nicht empfehlen, eine Liste Verständnis mit und stattdessen unter Verwendung eines gewöhnlichen for-Schleife:

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

aber Ihr Problem ist wirklich nicht, dass Sie sollten nicht Ihr Set Pixel für jede Farbe anrufen separat. Wenn möglich, Ihre API ändern, so dass Sie diese wie vorgeschlagen tun können durch 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 Dies wird lediglich das Hinzufügen hässliche Abhilfen zu einem hässlichen API. Es ist API-Redesign-Zeit - siehe die Antwort von @Muhammad Alkarouri, oder meins. –

+0

@John Machin: Entschuldigung, ich hätte das erwähnen sollen. Mein Plan war, zuerst eine genaue Antwort auf die genaue Frage zu geben und dann das Gesamtbild zu behandeln und die alternativen Ansätze zu erklären. Aber während ich den ersten Teil tippte, schlugen mich schon andere auf den zweiten Teil.Ich wollte nicht nur genau die gleichen Informationen kopieren, die andere bereits in meinem Post gepostet hatten, also habe ich sie einfach so belassen wie sie war, denn niemand anders hat die Frage beantwortet. Jetzt sehe ich, dass meine Antwort akzeptiert wurde und ich meine Antwort nicht löschen kann. Also habe ich deine Antwort in meinen Beitrag aufgenommen. Ist das in Ordnung? Oder was schlägst du vor, dass ich tun sollte? –

+0

Ich würde durch das Muster der Stimmen sagen, dass Ihre Verweisung auf die andere Antwort funktioniert oder nicht gebraucht wird, also denke ich, dass Sie sich jetzt darüber nicht sorgen sollten. Und danke, dass du mich als "andere, die mich geschlagen haben" erwähnt hast :) –

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

würde ich ein benanntes Tupel verwenden, um die Farbe zu repräsentieren, und die Klasse ändern Farbe zu verwenden, Attribute eher als einzelne get_pixel(x,y,c). Zum Beispiel:

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) 

bearbeiten: Dank John Machin für die Korrekturen hier vorgeschlagen. Seine Antwort gibt auch mehr Einblick in die Gründe für diesen Ansatz. Ich würde hinzufügen, dass ein namedtuple den Vorteil gibt, Felder wie color.red, color.green, zu haben, die ich gerne zur Verfügung habe. YMMV.

+0

Dazu müssen entweder die Argumente von 'function' (die dem OP möglicherweise nicht" gehört ") oder' t = function (* color) 'geschrieben werden. –

+0

@ John Machin: ganz richtig. Ich habe das '*' vergessen, weshalb ich ein Tupel benutzt habe. Ich habe gerade die Antwort bearbeitet, um sie zu korrigieren. –

+0

und die letzte Zeile sollte "self.set_pixel (x, y, color)" sein –

5

Wie Sie self verwenden, scheint es, dass get_pixel etc sind Methoden der Ihre Klasse. Anstatt Listenkompromittierungen und zip() und andere Problemumgehungen, sehen Sie sich die APIs an und beheben Sie sie. Zwei Vorschläge:

  1. Schreiben Sie eine andere Methode get_pixel_colors(x, y), die ein 3-Tupel zurückgibt. Dann können Sie r, g, b = self.get_pixel_colors(x, y)
  2. Ähnlich schreiben: self.set_pixel_colors(x, y, r, g, b)

Noch besser ist, können Sie die *args Notation:

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