a lambda in a function
Burton Radons
notrub-snodar at shaw.ca
Wed Dec 12 21:20:18 EST 2001
Fred Clare wrote:
> Why does interpreting the five lines:
>
>
> def func():
> x = 1
> add_one = lambda i: i+x
> j = add_one(100)
> func()
>
>
> Give me:
>
> Traceback (most recent call last):
> File "test.py", line 6, in ?
> func()
> File "test.py", line 4, in func
> j = add_one(100)
> File "test.py", line 3, in <lambda>
> add_one = lambda i: i+x
> NameError: There is no variable named 'x'
>
>
> while interpreting the three lines:
>
>
> x = 1
> add_one = lambda i: i+x
> j = add_one(100)
>
> works just fine?
It's a matter of scope vagaries. This is answered in the FAQ, question
4.5 at (http://www.python.org/cgi-bin/faqw.py?req=show&file=faq04.005.htp):
4.5. When I define a function nested inside another function, the nested
function seemingly can't access the local variables of the outer
function. What is going on? How do I pass local data to a nested function?
Python does not have arbitrarily nested scopes. When you need to create
a function that needs to access some data which you have available
locally, create a new class to hold the data and return a method of an
instance of that class, e.g.:
class MultiplierClass:
def __init__(self, factor):
self.factor = factor
def multiplier(self, argument):
return argument * self.factor
def generate_multiplier(factor):
return MultiplierClass(factor).multiplier
twice = generate_multiplier(2)
print twice(10)
# Output: 20
An alternative solution uses default arguments, e.g.:
def generate_multiplier(factor):
def multiplier(arg, fact = factor):
return arg*fact
return multiplier
twice = generate_multiplier(2)
print twice(10)
# Output: 20
----
Note that this has been solved in the 2.1 series thanks to PEP 227
(Nested Scopes), as a __future__ feature. In 2.2 nested scopes were
added as default. If you can't upgrade or if your code has to work on
older versions, you'll have to use default arguments.
The second works because you're adding variables to the global
dictionary, rather than a local dictionary that is specific to that
frame. Hope that helps.
More information about the Python-list
mailing list