3

I'm new to python, and wondering why it can access the variable defined in main program from outside, but can't in a self-defined function.

def f():
    print(l)

if __name__ == '__main__':
    l = [1,2,3]
    f()         # output: [1,2,3]

but encounter error when do it in a function

def f1():
    l1 = [1,2,3]
    f2()

def f2():
    print(l1)    # error: global name 'l1' is not defined

if __name__ == '__main__':
    f1()        

The first example really confused me, AFAIK, it's an error in C/C++ or some other languages, because we can't reference a undefined variable. So why it's legal here and why the second example is not legal?

3 Answers 3

5

The if block is not scoping the variable, it's merely conditionally declaring it. If your program is running as __main__ (i.e. is the primary script being executed), l will be declared as globally scoped variable, and hence is available when f is executed. It's the same as:

if True:
    l = []

def f1():
    print(l)

Which is the same as:

l = []

def f1():
    print(l)

It does not matter whether l is declared before or after the function, it only matters that it's declared by the time the function body is executed.

However, declaring the variable inside the function f1 scopes it to f1.

Sign up to request clarification or add additional context in comments.

Comments

1

Let's break down your code:

First, you define a function named f1(). and you define a variable named l1 in f1(). And f1 will call f2():

def f1():
    l1 = [1,2,3]
    f2()

And then, here is another function named f2() , and this will print l1

def f2():
    print(l1)

Then, you'll call the f1()

if __name__ == '__main__':
    f1()        

What's wrong?

From help(global):

The "global" statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.

It would be impossible to assign to a global variable without "global", although free variables may refer to globals without being declared global.

As you can see, you should use global before you define l1 . So try this:

def f1():
    global l1
    l1 = [1,2,3]
    f2()

def f2():
    print(l1)

if __name__ == '__main__':
    f1()

Demo:

[1, 2, 3]

And you also can use l1 as a argument like this:

def f1():
    global l1
    l1 = [1,2,3]
    f2(l1)

def f2(arg):
    print(arg)

if __name__ == '__main__':
    f1()

That's OK, and arg is a variable, you can use it in the function.

Comments

0

l in the first example is defined globally and is therefore automatically in all functions (read-only, mind you), as soon as you do l=1 within function scope it will be a local variable unless you explicitly add a global l (which is bad practise usually).

1 Comment

"Read-only" is not exactly correct. You can modify the value if the value is mutable. E.g. l.append(4) will work just fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.