# Index not recognized

I’m making a calculator in python and I’ve run into a little problem when processing parentheses. Here’s the code:

``````def split_par(lst):
lst_two = lst.copy()
for i in lst_two:
if i == '(':
index = lst_two.index(i)
del lst_two[0:index + 1]
elif i == ')':
close_index = lst_two.index(i)
del lst_two[close_index:]
del lst[index:close_index + 1]
str = pemdas_op(lst_two)
lst.insert(index, str)
if '(' in lst:
split_par(lst)
return lst
``````

If I run this code with an input of, for example, `['(', 12, '+', 7, ')', '*', '(', 12, '+', 7, ')']`, it’ll give me the following error: `UnboundLocalError: local variable 'index' referenced before assignment`
What I find fascinating is if I change `del lst[index:close_index + 1]` to `del lst[index:close_index + 2]` It wont give me an error. It will give me the following output: `[19, '*', 19, 7, ')']` Which is obviously not what I need. Also I will detail that the line `str = pemdas_op(lst_two)` is calling a separate function in my program that runs the list through a stack and consolidates the equations based on the order of operations. I don’t think it’s necessary to see that one but if it is let me know. Anyways, how can I solve this problem?

Don’t remove elements from a list while you’re iterating over it. This changes the output of the iterator and the indexes.

If you call this function with a list where a “)” occurs before a “(”, then you will enter the `elif` before you enter the `if` block.

Since the if block hasn’t had a chance to assign a value to `index`, it throws an error when that value is attempted to be read in the second `del` line.

Hello, @pattydaone. You can try updating your split_par() code like this:

``````def split_par(lst):
lst2 = lst.copy()
lst3 = lst.copy()
lst.clear()
foundPhStart = False
textOutsidePh = []
for i in lst2:
if i == "(":
foundPhStart = True
if textOutsidePh != []:
pemdasopStr2 =  pemdas_op(textOutsidePh)
lst.append(pemdasopStr2)
textOutsidePh.clear()
del lst3[0:(lst3.index(i)+1)]
elif foundPhStart == False:
textOutsidePh.append(i)
elif i==")":
foundPhStart = False
pemdasopStr4 = pemdas_op(lst3[0:lst3.index(i)])
lst.append(pemdasopStr4)
del lst3[0:(lst3.index(i)+1)]
if textOutsidePh != []:
pemdasopStr3 = pemdas_op(textOutsidePh)
lst.append(pemdasopStr3)
return lst
``````

I don’t think I ever thought of it because (as far as I’m concerned at least) there’s not an instance where you’ll put a closing parentheses before an opening one in a mathematical expression, so I just ignored that as a potential issue. However you are right. With further inspection I see that the issue does lie in the `elif` section of the function. So I changed the code to this to solve the issue:

``````def split_par(lst):
if '(' in lst:
lst_two = lst.copy()
for i in lst_two:
if i == '(':
index = lst_two.index(i)
index_one = lst.index(i)
del lst_two[0:index + 1]
elif i == ')':
close_index = lst_two.index(i)
index_two = lst.index(i)
del lst_two[close_index:]
del lst[index_one:index_two + 1]
str = pemdas_op(lst_two)
lst.insert(index_one, str)
print(lst)
split_par(lst)
else:
return lst
``````

Unfortunately this code also has a problem, as goes with programing, that (I hope) you can help with. As the code stands, if I input `['(', 12, '+', 7, ')', '*', '(', 12, '+', 7, ')']`, it will return none. I honestly don’t know what the issue is because the little `print(lst)` block at the bottom will print `[19, '*', 19]` which should then be recursed through the function, where it will fail the initial `if` statement and go to the `else` statement where it should return `[19, '*', 19]`, but it doesn’t. It returns `None`. Clearly I’ve done something wrong in my understanding of what’s going on, and I don’t know what I’ve missed.

The return returns to the most recent caller. Your code is doing something like this (I didn’t follow the logic exactly, but it’s close)…

``````split_par(<first sequence>)
... # does some stuff
split_par([19, '*', 19])
...
return [19, '*', 19]
... #ignores the return value from split_par()
returns None
``````

It is possible you want to change the recursive call to

``````  return split_par(lst)
``````

But since you haven’t included `pemdas_op`, I can’t run the program.

Here’s the `pemdas_op` function if you’d like:

``````def pemdas_op(lst):
lst_index = 0
pemdas_stack = ['^', '*', '/', '+', '-']
while pemdas_stack and len(lst) > 1:
popped = pemdas_stack.pop(lst_index)
if popped in lst:
index = lst.index(popped)
if lst[index] == '^':
first = index - 1
second = index + 1
amount = lst[first] ** lst[second]
del lst[first:second+1]
lst.insert(first, amount)
elif lst[index] == '*':
first = index - 1
second = index + 1
amount = lst[first] * lst[second]
del lst[first:second + 1]
lst.insert(first, amount)
elif lst[index] == '/':
first = index - 1
second = index + 1
amount = lst[first] / lst[second]
del lst[first:second + 1]
lst.insert(first, amount)
elif lst[index] == '+':
first = index - 1
second = index + 1
amount = lst[first] + lst[second]
del lst[first:second + 1]
lst.insert(first, amount)
elif lst[index] == '-':
first = index - 1
second = index + 1
amount = lst[first] - lst[second]
del lst[first:second + 1]
lst.insert(first, amount)
else:
continue

str = 0
if len(lst) == 1:
for i in lst:
str += i
return str
``````

Although I did change that one line to `return split_par(lst)` and it worked almost seamlessly, so, thank you.