Colonel Panic
Colonel Panic

Reputation: 137682

Surprising behaviour of enumerate function

I wrote some Python code using the enumerate function.

A = [2,3,5,7]

for i, x in enumerate(A):
    # calculate product with each element to the right
    for j, y in enumerate(A, start=i+1):
        print(x*y)

I expected it to calculate 6 products: 2*3, 2*5, 2*7, 3*5, 3*7, 5*7

Instead, it calculated all possible 16 products. What's going on?

Upvotes: 0

Views: 76

Answers (2)

Yann Vernier
Yann Vernier

Reputation: 15887

The question here is firstly what enumerate did, and secondly why you're using it. The base function of enumerate is to convert an iterable of the form (a,b,c) to an iterable of the form ((start,a), (start+1,b), (start+2,c)). It adds a new column which is typically used as an index; in your code, this is i and j. It doesn't change the entries contained in the sequence.

I believe the operation you were intending is a slice, extracting only part of the list:

for i, x in enumerate(A):
  for y in A[i+1:]:
    print(x*y)

If it is important not to copy the list (it rarely is), you can replace A[i+1:] with itertools.islice(A, i+1, len(A)).

A side note is that the start argument may be useful in the outer loop in this code. We're only using i+1, not i so we may as well use that value as our index:

for nextindex, x in enumerate(A, 1):
  for y in A[nextindex:]:
    print(x*y)

Upvotes: 2

deceze
deceze

Reputation: 522412

The start parameter of enumerate solely influences the first value of the yielded tuple (i.e. i and j), it does not influence at which index the enumeration starts. As the manual puts it, enumerate is equivalent to this:

def enumerate(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1

What you want is this:

for i, x in enumerate(A):
    for y in A[i + 1:]:
        print(x * y)

Upvotes: 7

Related Questions