Python Warts

misfeatures and other problems
PERL| PHP| PYTHON| RUBY
Answers: (all questions)
(question)
Question:
#!/usr/bin/python

def outer():
	i=1
	def inner():
		print "i=%s" % str(i)
		i += 1
	
	inner()
	inner()

outer()
Answer:
This program fails due to a scoping error:
Traceback (most recent call last):
  File "q/function_scope-2.py", line 12, in ?
    outer()
  File "q/function_scope-2.py", line 9, in outer
    inner()
  File "q/function_scope-2.py", line 6, in inner
    print "i=%s" % str(i)
  UnboundLocalError: local variable 'i' referenced before assignment
Python has an unusual scoping system, where functions are pre-scanned for assignments before they are executed. Any variable which gets assigned is assumed to be local unless explicitly declared global.

This issue is further complicated by Python's lack of a way to access parent variables which are not global. In this case, there are three nested scopes: global, outer, and inner. But inner has no direct way to access outer's data for assignment. The only way to assign data from inner to outer is to wrap the data in containers so Python's optimizer will not detect any assignment, and will not create local variables to override the parent data.

This version of the code works:
 #!/usr/bin/python

def outer():
	i=[1]
	def inner():
		print "i=%s" % str(i[0])
		i[0] += 1
	
	inner()
	inner()

outer()
PERL| PHP| PYTHON| RUBY
Last modified: March 30, 2006 @ 7:04 MST
Copyright (C) 1996-2017 Selene Scriven