3

So I've got some code similar to this (this code reproduces my question, even if it doesn't do anything useful):

def fn():
    l = ["foo", "bar", "baz"]
    print map( lambda f : len(f), l )
    for i, f in enumerate(l):
        print i, f

And PyCharm is reporting that my declaration of lambda f "Shadows name f from outer scope". This appears to be because of the variable being reused in the call to enumerate() in the following line.

The code works as expected, but what's happening here? Am I correct in thinking that Python is deciding that f is a local variable in fn and warning me that the use of f inside the lambda isn't going to be the same f defined locally - even though the lambda makes use of the variable name f first?

Other than renaming variables, is there a best practice for avoiding this - or should I just use my judgement and ignore the warning in this instance?

Floomi
  • 2,503
  • 2
  • 16
  • 10

1 Answers1

1

Assigning to a variable anywhere in the definition of a function makes it local to the function. A more typical example is

x = 3
def foo():
    print x
    x = 2
foo()

When foo is defined, the presence of x = 2 without a previous global x statement makes x a local variable. When foo is called, the local variable x is not yet defined when print x is called, resulting in an UnboundLocalError. It doesn't matter that there is a global variable by the same name.

In your example, the for loop is a kind of implicit assignment to the variable f, so f is local to fn. The warning is to let you know that the lambda argument f takes precedence over the value of f in fn when it comes time to evaluate len(f).

chepner
  • 497,756
  • 71
  • 530
  • 681
  • sorta-kinda like [javascript hoisting](https://www.w3schools.com/js/js_hoisting.asp) except Python doesn't have declarations, except this means it kinda does... – dwanderson Feb 22 '17 at 02:26