Reputation: 16406
I was staring at a piece of Python code I produced, which, though correct, is ugly. Is there a more pythonic way of doing this?
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)
The problem is the repetition of the method calls for get_pixel
and set_pixel
. For your information:
RED, GREEN, BLUE = range(3)
Also note that I'd like to preserve code clarity and cleanness.
Upvotes: 6
Views: 242
Reputation: 838276
To call a function with different arguments and collect the results you can use a list comprehension:
r1, r2, r3 = [foo(x) for x in [x1, x2, x3]]
To call a function for its side-effects I'd recommend not using a list comprehension and instead using an ordinary for loop:
ijs = [(i1, j1), (i2, j2), (i3, j3)]
for i, j in ijs:
bar(i, j)
However your problem really is not that you should not be calling your set pixel for each color separately. If at all possible, change your API so that you can do this as suggested by 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)
Upvotes: 1
Reputation: 24662
I would use a named tuple to represent the color, and change the class to use color attributes rather than individual get_pixel(x,y,c)
.
For example:
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)
Edit: thanks to John Machin for the corrections suggested here. His answer also gives more insight into the reasons for this approach. I would add that a namedtuple
gives the advantage of having fields such as color.red
, color.green
, color.blue
which I like to have available. YMMV.
Upvotes: 4
Reputation: 82934
As you are using self
, it appears that get_pixel
etc are methods of your class. Instead of list comprehensions and zip()
and other workarounds, look at the APIs and fix them. Two suggestions:
get_pixel_colors(x, y)
which returns a 3-tuple. Then you can write r, g, b = self.get_pixel_colors(x, y)
self.set_pixel_colors(x, y, r, g, b)
Even better, you can use the *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)
Upvotes: 5
Reputation: 123518
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)
Upvotes: 1