简体   繁体   中英

Why can a python function use a variable in the global scope before it's defined?

def foo(i):
  print len(A)
  return i < len(A)

if __name__ == '__main__':
  A = [12]
  print A 
  foo(10)

How can foo know about A ?

I am writing this because stackoverflow insists that I write some more words.

Check the generated bytecode:

>>> dis.dis(foo)
  2           0 LOAD_GLOBAL              0 (print) 
              3 LOAD_GLOBAL              1 (len) 
              6 LOAD_GLOBAL              2 (A) 
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             12 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             15 POP_TOP              

  3          16 LOAD_FAST                0 (i) 
             19 LOAD_GLOBAL              1 (len) 
             22 LOAD_GLOBAL              2 (A) 
             25 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             28 COMPARE_OP               0 (<) 
             31 RETURN_VALUE

To load the A variable it uses the LOAD_GLOBAL opcode. So, when the function runs ( and not at definition ) it will search for this variable in the global namespace

A is a global variable. You may be thinking that it is local to the if __name__ == '__main__' block, but if statements do not create a separate namespace in Python . When foo is executed (not defined) the variable A exists in the global namespace so your current code runs without any issues.

If you want to see your expected behavior move everything from that block into a function and then call that from within the if __name__ == '__main__' block:

def foo(i):
  print len(A)      # A is local to main(), so this will raise an exception
  return i < len(A)

def main():
  A = [12]
  print A 
  foo(10)

if __name__ == '__main__':
  main()

Because A is defined in the global scope, and isn't looked up in the function until it's called.

It's the same reason

def should_fail():
   print undefined_variable

print "runs OK!"

runs OK.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM