Confusing change of scope - what's going on?
def Test(value):
def innerFunc():
print value
innerFunc()
def开发者_如何学JAVA TestWithAssignment(value):
def innerFunc():
print value
value = "Changed value"
innerFunc()
Test("Hello 1")
# Prints "Hello 1"
TestWithAssignment("Hello 2")
# Throws UnboundLocalError: local variable 'value' referenced before assignment
# on the "print value" line
Why does the second one fail, given that the only difference is an assignment which comes after the print statement? I am pretty confused about this.
The issue is that Python wants you to be explicit and you want to be implicit. The execution model that Python uses binds names to the nearest available enclosing scope.
def Test(value):
# Local Scope #1
def innerFunc():
# Local Scope #2
print value
# No immediate local in Local Scope #2 - check up the chain
# First find value in outer function scope (Local Scope #1).
# Use that.
innerFunc()
def TestWithAssignment(value):
# Local Scope #1
def innerFunc():
# Local Scope #2
print value
# Immediate local variable found in Local Scope #2.
# No need to check up the chain.
# However, no value has been assigned to this variable yet.
# Throw an error.
value = "Changed value"
innerFunc()
There is not (as far as I know) a way to walk up the scope in Python 2.x - you have globals()
and locals()
- but any scopes between the global and the local scope cannot be accessed (if this is not true, I'd love to be corrected).
However, you can pass the local variable value
into your inner local scope:
def TestWithAssignment(value):
def innerFunc(value):
print value
# Immediate local **and assigned now**.
value = "Changed value"
# If you need to keep the changed value
# return value
innerFunc(value)
# If you need to keep the changed value use:
# value = innerFunc(value)
In Python 3 you have the new nonlocal
statement that can be used to refer to the containing scope (Thanks @Thomas K).
def TestWithAssignment(value):
def innerFunc():
nonlocal value
print value
value = "Changed value"
innerFunc()
This should fix it:
def Test(value):
def innerFunc(value):
print value
innerFunc(value)
精彩评论