Reputation: 29
I've declared 2 variables the same exact way, but when I'm calling them stack is being referenced fine. But python is not able to reference top. What is the issue here?
def isValid(s):
top=-1
stack=[-1]*10005
def push(x):
print(top)
top+=1
stack[top]=x
push()
print(isValid(input()))
Upvotes: 2
Views: 1402
Reputation: 1080
top is pointing to a literal hence it is immutable and stack is a mutable object if you wanted to solve the problem with top which is not actually a problem, you have 2 options.
example:
case: 1
def isValid(s):
top=-1
stack=[-1]*10005
def push(x):
nonlocal top
print(top)
top+=1
stack[top]=x
case 2:
def isValid(s):
top= {'value': -1}
stack=[-1]*10005
def push(x):
print(top)
top['value']+=1
stack[top]=x
Upvotes: 0
Reputation: 31319
The difference lies in how you access the variable, which causes it to be treated differently. Consider this:
def isValid():
top = -1
def push():
print(top)
push()
isValid()
Here there is no error, since top
can be found in the scope of isValid()
and calling push()
will print it correctly. However, if you add top += 1
, Python correctly infers that top
apparently has to be a local variable for that to work, but it isn't, so now top
is showing as problematic everywhere inside push()
(in most IDEs).
def isValid():
top = -1
def push():
print(top) # you'll see error messages / highlighting for top here
top += 1 # and here as well
push()
isValid()
Note that top += 1
isn't even the first statement, but its presence causes print(top)
to no longer work either, since top
now has to be local. But since there's no assignment to top
before the other two statements, Python will correctly complain that it has been accessed before having been assigned.
The reason this doesn't happen with your stack
is that you're not actually trying to change stack
inside push()
. You're trying to change one of its elements (stack[1]
), but that doesn't change what object stack
is naming - you're not assigning to stack
itself, so it does not become local.
So, Python finds stack
in the scope of isValid
, allows you to access it (just like top
in the first example) and you can access its elements without issue.
Upvotes: 0
Reputation: 11240
The previous answer is mostly correct. Python considers any variable that you directly change the value of to be a local variable. Since you write top += 1
, top
is directly modified inside push
, and is a local variable to push
. The variable stack
, on the other hand, is not changed.
I consider the fact that Python considers +=
operators to cause a variable to become local to be a bit of a bug. But it's too ingrained in the language.
And yes, the correct solution is to use nonlocal
.
If you removed the top += 1
line, your code wouldn't work, but top
would refer to the outer variable.
Upvotes: 1
Reputation: 11486
Because push
is indented inside isValid
, it can't change the value of top
from its "parent" function.
You can use nonlocal
:
def isValid(s):
top=-1
stack=[-1]*10005
def push(x):
nonlocal top
print(top)
top+=1
stack[top]=x
Upvotes: 0