# FAQ: List Comprehension - Product

if there are three sublists why does the syntax for this exercise work that way?

Hey,
In the example, `new_list = [item1 + item2 for (item1, item2) in original_list]`, parentheses are used to define `item1` and `item2`.

The example could be written as `new_list = [item1 + item2 for item1, item2 in original_list]` and the same result occurs.

What situations would it be useful to define with parenthesis?

It’s one of those things that can go either way. Doesn’t hurt readability.

There are cases where grouping is needed for operator precedence, albeit this is not one of them.

Product

Example nothing like the answer. Where is this ‘e’ business coming from?

Not sure what “‘e’ business” you are referring to. This lesson expects a list of products, not sums.

Great question. I’d rather use a function in this case. For example, [prod(l) for l in list], where prod(l) is a function that computes a product of every elements in a list l. If list = [[1,2], [1,2,3]], then we will get [2, 6]. You can define this prod function on your own, but there already exists such a function. Here is an example:

``````from math import prod
lists = [[1,2], [1,2,3]]
[prod(list) for list in lists]
``````

This will give [2,6].

I would love to hear other options.

Hi,
What is the difference between brackets and parenthesis ? Can we use both and vice-versa ?

Is

new_list = [item1 + item2 for (item1, item2) in original_list]

equivalent to

new_list = [item1 + item2 for [item1, item2] in original_list]

?

Thanks for the feedback.

You would be creating a tuple instead of a list. They both end up in the same final result here. Since you’re not using the list again it may as well be a tuple. It’s not too important at this point but you should try to avoid creating objects you don’t need.

Technically the parentheses here aren’t necessary either, you can keep them if you think they’re more readable though-

``````new_list = [item1 + item2 for item1, item2 in original_list]
``````

Ok thanks. I have the impression that in the exercice we create a tuple rather than a list then (since the results shows parenthesis). But we use list(). This I do not understand…

Print is only ever a representation of the objects stored but the standard output for a list would be using square brackets `[]` and parentheses for a tuple `()`.

print(list()) print(tuple()) print([x for x in range(0)])

Based on what you’ve written above, `new_list` will always be a list as it is created via a list comprehension. You’ll need to explain more or post the full code as it’s nothing but guesswork otherwise- How do I format code in my posts?.

Hi tgrtim,

Sure, I can show an example. In the exercice of Frida Kahlo, we have at the beginning the following code:

paintings = ['The Two Fridas', 'My Dress Hangs Here', 'Tree of Hope', 'Self Portrait With Monkeys'] dates = [1939, 1933, 1946, 1940] paintings = list(zip(paintings, dates)) print (paintings)

I see that the result `('The Two Fridas', 1939)` is in parenthesis (even if it was defined in brackets at the beginning), while the entire nested list is in brackets.
But if I append new element of a list in this way below, the result will give me a mix of parenthesis () and brackets. Why ? What kind of object do I have created?

paintings = ['The Two Fridas', 'My Dress Hangs Here', 'Tree of Hope', 'Self Portrait With Monkeys'] dates = [1939, 1933, 1946, 1940] paintings = list(zip(paintings, dates)) print (paintings) paintings.append(['The Broken Column', 1944]) paintings.append(['The Wounded Deer', 1946]) paintings.append(['Me and My Doll', 1937]) print (paintings)

You’re correct that would indeed be a tuple (or the overall object would be several tuples stored in a list) but that’s the standard return from `zip`. You can see the tuple output in the following example and I’ve included some options which would create lists instead-

# what does zip return? for element in zip("a"): print(element) print(type(element)) for element in zip("a"): element = list(element) print(f"\n\n{element}") comprehension = [element for element in zip("a")] print(f"\n\n{element}")

It’s always worth having a little look at the docs for functions you may be less familiar with, the parameters and returns should be provided-
https://docs.python.org/3/library/functions.html#zip

Ok, now I have a better comprehension. Thanks a lot.

1 Like

I was wondering the same, e1 * e2. why do we refer to these positions with an “e” ?. after reading the example I used item1 * item2

Any names may be used, and depending the situation, longer names that self document the code, or when sufficient, short, symbol names when the operation is self explanatory.

``````    e1, e2
item1, item2
a, b
``````

All are valid. They’re just variables. Name for meaning, not verbosity.

1 Like

Gotcha thanks for the fast reply

1 Like

I tried using a for loop differently from the solution but my output is garbled with generator objects.

My code:

``````for items in nested_lists:
product.append(item1 * item2 for (item1, item2) in items)
``````

What my code yields:

``````[<generator object <genexpr> at 0x7f0c5e0fdc50>, <generator object <genexpr> at 0x7f0c5e0c37d8>, <generator object <genexpr> at 0x7f0c5e0c3830>]
``````

How do I get the intended content to show in the list instead of the generator objects?

List comprehensions require the surrounding `[` and `]` to denote a list. Without you’re using a generator expression (a lazily evaluated iterator) that may be introduced at some point or you can search for it.

If I’m not mistaken though you don’t want a normal for loop at all in this example, just the list comprehension.

I had a question about list comprehensions for lists with more than one level of nesting. With a bit of testing I solved my own problem but I thought I’d share it here:

nested_lists = [[4, [8]], [15, [16]], [23, [42]]] product = [x*y for (x,[y]) in nested_lists] print(product)

Note that the ‘y’ had to be put between square brackets for it to work as I intended. When it was in parentheses it actually multiplied the list element (so first answer was [8,8,8,8]

Did you solve your problem or create a new one?

Given, two lists:

``````a = [2, 3, 5, 7, 11, 13, 17, 19]
b = [1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18]
``````

For no particular reason I’ve made the first list all the primes less than 20 and the second all the non-primes in the same range. Both the length and the values are disjoined, as in differing in every regard.

``````>>> c = [x for x in a for y in b if x % y == 0]
>>> c
[2, 3, 5, 7, 11, 13, 17, 19]
#  unity divisible only
>>> c = [y for x in a for y in b if x % y == 0]
>>> c
[1, 1, 1, 1, 1, 1, 1, 1]
# unity divisible prime factor
>>> c = [x for x in a for y in b if y % x == 0]
>>> c
[2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 5, 5, 7]
#  divisible by prime, occurrences
>>> c = [y for x in a for y in b if y % x == 0]
>>> c
[4, 6, 8, 10, 12, 14, 16, 18, 6, 9, 12, 15, 18, 10, 15, 14]
#  nonprime occurrences
>>>
``````

Comments added by the writer

Each nested comprehension gives a different answer. Which one is valid for our purposes?

The language promises us a data structure in return. We humans get to decide if the data is valid and/or meaningful. These sorts of experiments do require us to have some expectations.