Using multiple variables in a for loop in Python

112,285

Solution 1

The simplest and best way is the second one, not the first one!

for i in array:
    do_something(i)

Never do this, it's needlessly complicating the code:

for i in range(len(array)):
    do_something(array[i])

If you need the index in the array for some reason (usually you don't), then do this instead:

for i, element in enumerate(array):
    print("working with index", i)
    do_something(element)

This is just an error, you will get TypeError: 'int' object is not iterable when trying to unpack one integer into two names:

for i, j in range(len(array)):
    # What is i and j here?

This one might work, assumes the array is "two-dimensional":

for i, j in array:
    # What is i and j in this case?

An example of a two-dimensional array would be a list of pairs:

>>> for i, j in [(0, 1), ('a', 'b')]:
...     print('i:', i, 'j:', j)
...     
i: 0 j: 1
i: a j: b

Note: ['these', 'structures'] are called lists in Python, not arrays.

Solution 2

Your third loop will not work as it will throw a TypeError for an int not being iterable. This is because you are trying to "unpack" the int that is the array's index into i, and j which is not possible. An example of unpacking is like so:

tup = (1,2)
a,b = tup

where you assign a to be the first value in the tuple and b to be the second. This is also useful when you may have a function return a tuple of values and you want to unpack them immediately when calling the function. Like,

train_X, train_Y, validate_X, validate_Y = make_data(data)

More common loop cases that I believe you are referring to is how to iterate over an arrays items and it's index.

for i, e in enumerate(array):
    ...

and

for k,v in d.items():  
    ...

when iterating over the items in a dictionary. Furthermore, if you have two lists, l1 and l2 you can iterate over both of the contents like so

for e1, e2 in zip(l1,l2):
    ...

Note that this will truncate the longer list in the case of unequal lengths while iterating. Or say that you have a lists of lists where the outer lists are of length m and the inner of length n and you would rather iterate over the elements in the inner lits grouped together by index. This is effectively iterating over the transpose of the matrix, you can use zip to perform this operation as well.

for inner_joined in zip(*matrix):  # will run m times
    # len(inner_joined) == m
    ...

Solution 3

Python's for loop is an iterator-based loop (that's why bruno desthuilliers says that it "works for all iterables (lists, tuples, sets, dicts, iterators, generators etc)". A string is also another common type of iterable).

Let's say you have a list of tuples. Using that nomenclature you shared, one can iterate through both the keys and values simultaneously. For instance:

tuple_list = [(1, "Countries, Cities and Villages"),(2,"Animals"),(3, "Objects")]

for k, v in tuple_list:
    print(k, v)

will give you the output:

1 Countries, Cities and Villages
2 Animals
3 Objects

If you use a dictionary, you'll also gonna be able to do this. The difference here is the need for .items()

dictionary = {1: "Countries, Cities and Villages", 2: "Animals", 3: "Objects"}

for k, v in dictionary.items():
    print(k, v)

The difference between dictionary and dictionary.items() is the following

dictionary: {1: 'Countries, Cities and Villages', 2: 'Animals', 3: 'Objects'}
dictionary.items(): dict_items([(1, 'Countries, Cities and Villages'), (2, 'Animals'), (3, 'Objects')])

Using dictionary.items() we'll get a view object containig the key-value pairs of the dictionary, as tuples in a list. In other words, with dictionary.items() you'll also get a list of tuples. If you don't use it, you'll get

TypeError: cannot unpack non-iterable int object

If you want to get the same output using a simple list, you'll have to use something like enumerate()

list = ["Countries, Cities and Villages","Animals", "Objects"]

for k, v in enumerate(list, 1): # 1 means that I want to start from 1 instead of 0
    print(k, v)

If you don't, you'll get

ValueError: too many values to unpack (expected 2)

So, this naturally raises the question... do I need always a list of tuples? No. Using enumerate() we'll get an enumerate object.

Solution 4

Actually, "the simplest way of using a for loop an iterating over an array" (the Python type is named "list" BTW) is the second one, ie

for item in somelist:
    do_something_with(item)

which FWIW works for all iterables (lists, tuples, sets, dicts, iterators, generators etc).

The range-based C-style version is considered highly unpythonic, and will only work with lists or list-like iterables.

What I would like to know is what this does

for i, j in range(len(array)):
    # What is i and j here?

Well, you could just test it by yourself... But the result is obvious: it will raise a TypeError because unpacking only works on iterables and ints are not iterable.

or

for i, j in array:
    # What is i and j in this case?

Depends on what is array and what it yields when iterating over it. If it's a list of 2-tuples or an iterator yielding 2-tuples, i and j will be the elements of the current iteration item, ie:

array = [(letter, ord(letter)) for letter in "abcdef"]
for letter, letter_ord in array:
    print("{} : {}".format(letter, letter_ord))

Else, it will most probably raise a TypeError too.

Note that if you want to have both the item and index, the solution is the builtin enumerate(sequence), which yields an (index, item) tuple for each item:

array = list("abcdef")
for index, letter in enumerate(array):
    print("{} : {}".format(index, letter)
Share:
112,285
Ely Fialkoff
Author by

Ely Fialkoff

Updated on October 26, 2021

Comments

  • Ely Fialkoff
    Ely Fialkoff over 2 years

    I am trying to get a deeper understanding to how for loops for different data types in Python. The simplest way of using a for loop an iterating over an array is as

    for i in range(len(array)):
        do_something(array[i])
    

    I also know that I can

    for i in array:
        do_something(i)
    

    What I would like to know is what this does

    for i, j in range(len(array)):
        # What is i and j here?
    

    or

    for i, j in array:
        # What is i and j in this case?
    

    And what happens if I try using this same idea with dictionaries or tuples?