Python: max() arg is an empty sequence

Viewed 541

I want to compare element by element some tuples within a list of tuples and print the maximum for each comparison. This is my code:

A = [(10, 50, 1), (20, 4, 100), (11, 21, 10), (1, 42, 60), (0, 7, 74)]
indices = [1, 2]
D = (A[i] for i in indices)

for col in range(3):
    print(max(D, key = lambda tpl: tpl[col])[col])

But the output is:

20
ValueError: max() arg is an empty sequence

If I modify the generator by materializing the list D, such that D=[A[i] for i in indices], I obtain the desired result, that is:

20
21
100

Why Do I get that error in the former implementation? Is there a way to fix it without materializing the list? Do you have some advice to improve the code?

Thank you

2 Answers

This happens because in the first case, D is a generator object. The thing to remember about generators is that they get exhausted after the first time you iterate through them. You cannot iterate through them a second time.

So the first time you do max(D, ...) it runs through the generator to calculate the maximum and prints 20. The second time you try the same thing, the generator is already empty from the first time you went through it.

This is not the problem when you expand the generator into a list with a list comprehension like so:

D = [ A[i] for i in indices ]

because you can iterate through a list as many times as you like.

Note from @chepner's comment below:

Exhaustion is a property of all iterators, not just generators. (You can iterate over a list multiple times because a list is an iterable, not an iterator, that gives you a different iterator each time you ask for one.)

A = [(10, 50, 1), (20, 4, 100), (11, 21, 10), (1, 42, 60), (0, 7, 74)]
indices = [1, 2]

for i in range(3):
    col=[]
    for index in indices:
        col.append(A[index][i])
    print(max(col))

output:

20
21
100
Related