Extending Python Syntax with @

David M. Cooke cookedm+news at physics.mcmaster.ca
Thu Mar 11 16:26:18 EST 2004


At some point, Kyler Laird <Kyler at news.Lairds.org> wrote:
> Richie Hindle <richie at entrian.com> writes:
>>[Cameron]
>>> Whenever you feel like a lambda, define a named function; 
>>[Kyler]
>>> How do you cleanly do that?
>>> 	foo = range(-10, 10)
>>> 	my_op = lambda x: float(x) / max(map(abs, foo))
>>> 	bar = map(my_op, foo)
>
>>foo = range(-10, 10)
>>def my_op(x):
>>    return float(x) / max(map(abs, foo))
>>bar = map(my_op, foo)
>
>>...did I misunderstand?
>
> Well, your solution depends on a global variable.  That's going to
> get *really* ugly if we move beyond the trivial example given here.
> There are other problems but they're apparently not obvious with 
> that example.

The lambda depends on a global variable too (or at least, a variable
up one scope).

> How 'bout some non-working code to shine some more light on it?  (If
> pressed, I should be able to come up with similar code that works!)
>
> 	def make_translation_function(GCPs, type, invert=False):
> 		if type == 'LSF' and len(GCPs) < 12:
> 			# Do lots of time-consuming magic to calculate A, B, ...
> 			return(
> 				lambda x, y: (
> 					x * A + y * B +
> 					x * y * C +
> 					...,
> 					x * G + y * H +
> 					x * y * I +
> 					...
> 				)
> 			)
> 		elif ... # Repeat lots of times for variations.
>
> 	map_im = foo.open('map.tif')
> 	map_translation = make_translation_function(map_im.get_GCPs, type='LSF')
>
> 	path_im = foo.open('path.tif')
> 	path_translation_i = make_translation_function(path_im.get_GCPs, type='LSF', invert=True)
>
> 	# Mark all points on map that are red in path.
> 	for (x, y) in all_red_pixels(path_im):
> 		(lon, lat) = path_translation_i(x, y)
> 		(x, y) = map_translation(lon, lat)
> 		map_im.putpixel((x, y), mark_val)
>
> Now, let's pretend that this is part of a larger program that's doing lots
> of things with, potentially, lots of images, and let's also say that we
> allow user-defined/imported extensions to make_translation_function().
> How are you going to make a *clean* solution using named functions?

Umm, easily? You don't have to refer to functions by their original
name; they are first-class objects.

def make_translation_function(GCPs, type, invert=False):
    if type == 'LSF' and len(GCPs) < 12:
        # Do lots of time-consuming magic to calculate A, B, ...
        def LSF_function(x, y):
            xy = x*y
            lon = x*A + y*B + xy*C + ...
            lat = x*G + y*H + xy*I + ...
            return (lon, lat)
        return LSF_function
    elif ... # Repeat lots of times for variations.

I've even optimized by premultiplying x and y, which couldn't do in
the lambda, and made the code clearer by breaking up the calculation.

-- 
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca



More information about the Python-list mailing list