Not understanding lamdas and scoping

Joshua Kugler jkugler at bigfoot.com
Wed Mar 26 22:02:04 CET 2008


I am trying to use lamdba to generate some functions, and it is not working
the way I'd expect.  The code is below, followed by the results I'm
getting.  More comments below that.

patterns = (
    ('[sxz]$', '$','es'),
    ('[^aeioudgkprt]h$', '$', 'es'),
    ('[^aeiou]y$', 'y$', 'ies'),
    ('$', '$', 's'),
    )

def z(*a):
    print a

def make_pattern(pattern, search, replace):
    def compare(word):
        z(pattern, search, replace)
    return compare

rules = [make_pattern(pattern, search, replace)
         for (pattern, search, replace) in patterns]

print 'make pattern'
for rule in rules:
    rule('noun')

rules = [lambda word: z(pattern, search, replace)
                            for (pattern, search, replace) in patterns]

print 'lambda/list comprehension'
for rule in rules:
    rule('noun')

rules = []
for pattern, search, replace in patterns:
    rules.append(lambda word: z(pattern, search, replace))

print 'lamda/for loop'
for rule in rules:
    rule('noun')

Ouptut:

make pattern
('[sxz]$', '$', 'es')
('[^aeioudgkprt]h$', '$', 'es')
('[^aeiou]y$', 'y$', 'ies')
('$', '$', 's')
lambda/list comprehension
('$', '$', 's')
('$', '$', 's')
('$', '$', 's')
('$', '$', 's')
lamda/for loop
('$', '$', 's')
('$', '$', 's')
('$', '$', 's')
('$', '$', 's')

Of course, in my real code, I'm not calling z(), but a couple of RE
search/replace functions (yes, I'm working on the Dive Into Python
pluralizer).

The first result is obviously the correct one.  But the next two don't make
sense.  Why do all the functions returned by lamda have the last input
values?

What am I missing?

OK, I figured out if I did this:

def make_pattern(pattern, search, replace):
    return lambda word: z(pattern, search, replace)

it would give correct results.  So, is there some scoping issue with lambda
that I'm not seeing?

Thanks!

j




More information about the Python-list mailing list