Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

StopIteration is being raised and I can't understand why (using next method)

I want my code to understand a string as a math expression, then output me this string with proper whitespaces.

  1. At first, I created my variables.
operators = ("+", "-", "*", "/", "%", "**", "//") # Math operators the code is going to identify in the string

oper = "20 *25" # The operation string before being formatted ('oper' stands for 'operation')
new_oper = "" # This is going to be the new operation string (desired output)

it = iter(oper.replace(" ", "")) # Removed all whitespaces from the operation string and made it an iterable
  1. I used the next() method once, just so he could understand this method (inside my loop) as the character that comes right after the character the loop is in.
next(it)
  1. Then I started my loop to check every single character in the operation string (already with no whitespaces).
for x in oper.replace(" ", ""):
    try: # This try checks if I'm able to use the next() method. If I'm not, x is the last character in the string.
        if x not in operators: # x is a number
            if next(it) in operators:
                new_oper += f"{x} " # If an operator comes right after a number, this number is printed with a whitespace, so they don't stay next to each other.
            else:
                new_oper += x   
        elif x in operators: # x is an operator
            if x == "*":
                if next(it) == "*":
                    new_oper += x # If another '*' comes after this '*', then it's a ** operator, so no whitespaces inserted (otherwise, they would be separated)
                else:
                    new_oper += f"{x} "
            elif x == "/":
                if next(it) == "/":
                    new_oper += x # Same here: if there are 2 '/' next to each other, it's another operator ('//'), so no whitespaces inserted
                else:
                    new_oper += f"{x} "
            else:
                new_oper += f"{x} "
    except RuntimeError:
        new_oper += x # x is the last character in the string, no needs to be formatted (it can't be an operator)
  1. Finally, after formatting everything, I wanted him to print the new string (new_oper).
print(new_oper)

Check out these outputs (different values for oper):

When

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

oper = "20 *2"

Output

Traceback (most recent call last):
  File "filename", line 12, in <module>
    if next(it) in operators:
       ^^^^^^^^
StopIteration

# Desired output: 20 * 2

When

oper = "20 +2"

Output

20 + 2 # Correct output (just changed the operator comparing to the last one)

When

oper = "10+ 3 *2"

Output

10 + 3*2
# Desired output: 10 + 3 * 2

I’d appreciate any approach for my problem. I’m not a python expert (far away from that), so I also would appreciate any suggestions or even fixes in my code that may not directly help my problem.

>Solution :

Firstly, you need to change the except RuntimeError: to except StopIteration: so that it is able to catch the StopIteration exception that is thrown by the next() when it reaches the end of the string.

You need to change the else to make it like this:

else:
    new_oper += f"{x} "
    next(it)

Here, the next(it) is so that the iterator is always in line with the value of x. You call next(it) once on all other path of the if except this one.

With these 2 changes, it works on the examples given.


Suggestion:

It might be easier to iterate over the string using enumerate like this:

oper2 = oper.replace(" ", "")
for index, x in enumerate(oper2):

instead of trying to keep the iterator and the loop in sync. This way, you can refer to the next character as oper2[index+1] (index is the index of the current character) and for the current character, you can use x.
For example, instead of next(it), you would write oper2[index+1]. This has the added benefit of being able to look further ahead (but you would need to do except IndexError: instead of except StopIteration:)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading