1

In C there is an option to decide whether we want to override a loop variable.

For example, i is overridden in this snippet:

int i = 3;
for (i = 0;i < 5;i++);

But i is not overridden in this snippet:

int i = 3;
for (int i = 0;i < 5;i++);

Haven't found a similar option in Python.

For example, i is overridden in this snippet:

i = 3
for i in range(5):
    pass

How to prevent i from being overridden in this case?

7
  • 2
    In C, you can create a block and declare a new instance of the variable in that block. In Python, you could create a nested function and define the variable within that function, then call the function from within the parent. Commented Mar 12, 2016 at 6:33
  • 3
    idenpendently of the whole issue of overriding, why not use a different var name? its not like you only a certain amount Commented Mar 12, 2016 at 6:59
  • Have a look on this stackoverflow.com/questions/291978/… Commented Mar 12, 2016 at 7:02
  • its just that both the i in c code are saved and used as different varaibles saved at different localities , having different scopes , the interior i has a loop scope so... my key of advice is the same as that of @Mixone why you want to have same variable...it would rather make your work more worse in a long go... evaluating that which variable scope ends where and which one is currently being used...instead use another variable Commented Mar 12, 2016 at 8:36
  • @TomKarzes Your comment reminds me of the classic JavaScript for loop bug and it's solved by opening a new function and calling it afterwards. Not sure whether Python can do better. Commented Mar 12, 2016 at 9:01

3 Answers 3

2

That has to do with scope. In the example in C that you listed, int i = 0 is inside the for loop scope(that 'i' in particular is a local member of that forloop. It's not that 'i' isn't being overwritten, it's that they're in 2 different localities, so they aren't related to one another at all(other than visually when you look at it).

Python scope: Short Description of the Scoping Rules?

Sign up to request clarification or add additional context in comments.

1 Comment

Yes I agree with you. I know scopes and I wrote this question to see if anyone has an elegant way to open a new scope in Python for this specific task.
1

You have to put the loop into a new scope. One way to do that is to use a function. Another way is to put it into a generator expression:

i = 3
a = min((i-10)**2 for i in range(5))
print(a, i)

output

36 3

Another option in Python 3 is to put the loop into a list comprehension, but in Python 2 that does not create a new scope (for efficiency reasons).

i = 3
a = min([(i-10)**2 for i in range(5)])
print a, i

output

36 4

That list comp isn't as efficient as the generator expression above: it uses more RAM, and min has to wait for the full list to be constructed, whereas in the generator expression version it can start processing values yielded by the gen exp straight away.

2 Comments

The list comprehension you pointed out is a good example of the difference between Python 2 and 3 (or called a bug of Python 2). I like using generator expression and list comprehension as you wrote here. But if the loop body has a non-trivial size then a for loop still have to be used. But I'm not aware of any Pythonic way of doing this using the same variable name.
@Cyker: I wouldn't call it a bug, but I agree it is natural to assume that a list comp would create a new scope. If the size is non-trivial then you should format the list comp over multiple lines, or if it's deeply nested break it up into separate list comps. Also, a list comp isn't a general substitute for a for loop. Eg, using a list comp purely for side-effects where you immediately discard the resulting list is un-Pythonic.
1

I suggest that using the same name to refer to different variables in the same function is bad practice. Even in C. There are plenty of other bad practices in C that you can't do in python, for example failing to indent.

My point is that the C case is undesirable. I concede that this is acceptable:

for (int i = 0; i < 42; i++) { ... }

for (int i = 0; i < 37; i++) { ... }

But having an outer version of i as well would be confusing.

Those kinds of loops are mostly used in C for iterating through arrays. In the example i is an int, but it could be a pointer that is being incremented.

Counting loops using range() are not needed nearly as much in python because we have object iterators.

A frustrated C programmer might do this in python:

for i in range(len(mylist)):
    print(mylist[i])

but the following is preferred:

for list_item in mylist:
    print(list_item)

So my second point is that the C case is unnecessary.

The philosophy in Python is based on objects and object iterators. In C you don't have that. In C myarray[i] is syntactic sugar for *(myarray + i), we just don't want that in python, we have many more different types of containers than C and iteration should be consistent.

I'm not saying you never need the index number, but there is always enumerate().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.