Same variable name for different values in nested loops.

前端 未结 6 1097
囚心锁ツ
囚心锁ツ 2020-12-22 12:26

This code is perfectly valid Python

x=[[1,2,3,4], [11,22,33,44]]
for e in x:
    for e in e:
        print e

Can someone please tell me why

6条回答
  •  清酒与你
    2020-12-22 12:54

    I suppose you could roughly translate the inner loop in that above expression to:

    for e in x:
        ee = iter(e)
        try:
            e = next(ee)
            while True
                print e
                e = next(ee)
        except StopIteration
            pass
    

    Note that the key thing here is in the statement: for e in ..., ... is converted to an iterator via the iterator protocol. The object you actually iterate over is a separate object from the e you gave it initially. Since it's a separate object (stored separately from its name in the current scope to allow it to be iterated over) there is no problem with binding a new variable to that name in the current scope -- Maybe I should say that there is no problem other than it makes the code really hard to follow.

    It's effectively the same reason you don't have a problem doing this:

    A = [['foo']]  #Define A
    b = A[0]       #Take information from A and rebind it to something else
    c = A          #We can even take the entire reference and bind/alias it to a new name.
    A = 'bar'      #Re-assign A -- Python doesn't care that A already existed.
    

    Here are a couple more things to think about:

    x = [1,2,3,4]
    for a in x:
        print a
        next(a)   #Raises an error because lists aren't iterators!
    

    Now a seldom used, (but sometimes necessary) idiom:

    x = [1,2,3,4]
    y = iter(x)   #create an iterator from the list x
    for a in y:
        print a
        #This next line is OK.  
        #We also consume the next value in the loop since `iter(y)` returns `y`!
        #In fact, This is the easiest way to get a handle on the object you're
        #actually iterating over.
        next(y)   
    

    finally:

    x = [1,2,3,4]
    y = iter(x)   #create an iterator from the list x
    for a in y:
        print a
        #This effectively does nothing to your loop because you're rebinding
        #a local variable -- You're not actually changing the iterator you're
        #iterating over, just as `A = 'bar'` doesn't change the value of
        #the variable `c` in one of the previous examples.
        y = iter(range(10))
    

提交回复
热议问题