Reputation: 3
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
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 range
s 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 range
s), 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