Soare Stefan
Soare Stefan

Reputation: 3

Does python not recognize a variable that I use in an if statement that is also used in a for?

I'm a beginner in python,I come from a c++background. So when I pop an element out, I got to start over the list and make the i = 0. Pycharm is giving me an warning when I make i = 0 that local variable i is not used, but is it local? If the if statement is in for, doesn't pycharm know that I'm referring to the variable I that I use in for?

 for i in range(0, len(animals)-1):
        if(i == 0 and animals[i]!="grass" and animals[i]!="leaves"):
            if animals[1]  in animals_dict[animals[0]]:
                a=animals.pop(1)
                animals_final.append(f"{animals[0]} eats {a}")
        elif(animals[i]!="grass" and animals[i]!="leaves"):
            if animals[i-1] in animals_dict[animals[i]]:
                a=animals.pop(i-1)
                i-=1
                animals_final.append(f"{animals[i]} eats {a}")
                i=0
            elif animals[i+1] in animals_dict[animals[i]] and i+1<=len(animals) :
                a=animals.pop(i+1)
                animals_final.append(f"{animals[i]} eats {a}")
                i=0`

Upvotes: 0

Views: 55

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155363

range is a special object type, and its iterators have their own state. Setting i = 0 doesn't change the fact that the range iterator will replace i with the next value "on deck" (so to speak) when the for loops again (this is a general trait of all for loops, but people often think of for loops over ranges as being "like C for loops" and mistakenly think it's incrementing the existing i, when it's really just producing a new i value from scratch on each loop).

If it helps, you can think of the Python for loop as behaving like a C++ for-each loop of the form:

for (auto i : sequence) {

}

Just like in Python, reassigning i inside that loop wouldn't change the value of i on the next loop, because it's replacing i with the new value from sequence.

If you want a C-style for loop in Python with arbitrary levels of control over the loop index, you're stuck simulating it with while loops, e.g.:

i = 0   # Initialize
while i < len(animals)-1:  # Test
    if(i == 0 and animals[i]!="grass" and animals[i]!="leaves"):
        if animals[1]  in animals_dict[animals[0]]:
            a=animals.pop(1)
            animals_final.append(f"{animals[0]} eats {a}")
    elif(animals[i]!="grass" and animals[i]!="leaves"):
        if animals[i-1] in animals_dict[animals[i]]:
            a=animals.pop(i-1)
            i-=1
            animals_final.append(f"{animals[i]} eats {a}")
            i=0
        elif animals[i+1] in animals_dict[animals[i]] and i+1<=len(animals) :
            a=animals.pop(i+1)
            animals_final.append(f"{animals[i]} eats {a}")
            i=0
    i += 1  # Increment step; some i = 0 lines might need to be i = -1 to correct

Just for funsies, I'll show a really terrible way to do this with a for loop and a coroutine-generator function:

def resettable_range(start, stop):  # Not bothering to accept 1 or 3 arguments for simplicity
    while True:
        rng = range(start, stop)
        for i in rng:
            start = (yield i)
            if start is not None:
                break
        else:
            return  # Ran to completion without being sent a new value; we're done
        # If we got here, loop was broken, so we loop with new start value

With that defined, you can write a loop like:

range_gen = special_range(0, 10)  # Must have named variable to send to
for i in range_gen:
    if some_condition:
        range_gen.send(0)  # Resets to 0
    elif some_other_condition:
        range_gen.send(i)  # Next loop will use same i value
    elif some_third_condition:
        range_gen.send(i-1)  # Next loop will back up to prior i value

To be clear, I don't recommend this approach. It's somewhat magical, and not particularly efficient if you regularly have to change i for the next loop (because it has to keep building new ranges), but it works. It might need to be even more complicated for your case though, since you'd need the ability to redefine the end of the range too (since the length of animals can change).

Upvotes: 2

Related Questions