Not understanding lamdas and scoping

J

Joshua Kugler

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
 
G

George Sakkis

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.

(...)

So, is there some scoping issue with lambda
that I'm not seeing?

Yes; it's not related to lambda though but to closures (whether
defined as lambdas or regular functions). See for example
http://groups.google.com/group/comp.lang.python/browse_frm/thread/94d1bba8ad56baf4

There should be an entry for this at http://www.python.org/doc/faq/programming/,
that's really an FAQ.

George
 
J

Joshua Kugler

G

George Sakkis

George -

Thanks for the quick and clear answer...that makes perfect sense. To
bad...I'd like to just use a list comprehension. :)

Did you actually read the replies on that thread ? You _can_ use a
list comprehension or a loop, all you have to do is bind the passed
values as default parameters:

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


George
 
C

castironpi

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,118
Latest member
LatishaWhy
Top