Reputation: 33
So I was trying to do some basic stuff list stuff in a different way, and I came across weird behaviour in this code. I'm not sure if its a compiler/machine dependent result and I can't even google this because I'm just so lost.
Edit: In response to some people, I get that my code is incorrect in its semantics, but the behaviour of the code after the mistake is what I wanted to understand. Thanks for the corrections though!
Here is the code:
import random
L = (int(input("For List 1, enter a number: ")) for i in range(random.randint(2, 5)))
L1 = (int(input("For List 2, enter a number: ")) for i in range(random.randint(2, 6)))
common = []
for i in L:
if i in L1:
common.append(i)
print(common)
From my limited understanding, line 3 and 5 should have just resulted in L and L1 having the last entered integer stored in them, but when I execute the program it just flits between line 3 and 5. Furthermore, if I try to print L and L1 it just prints its object type (genexpr) and location in memory, before the prompts for inputs. Why is the code behaving that way?
Upvotes: 1
Views: 457
Reputation: 78780
The unexpected bahavior is caused by the generator expressions, which are evaluated lazily.
This means that the values for L
and L1
will be generated as needed, one value at a time.
The loop
for i in L:
can be executed by creating a single value for L
in each iteration.
This is why you will see one prompt "For List 1, enter a number: "
for each iteration of the outer for
loop!
However, the if
statement
if i in L1:
requires values to be created for L1
until i
is found or until there are no more values to generate for L1
.
Example:
>>> L1 = (x for x in (1, 2, 3, 4))
>>> 3 in L1
True
>>> next(L1)
4
>>> next(L1)
Traceback (most recent call last):
[...]
StopIteration
To avoid the lazy evaluation, use lists instead of generator expressions, i.e.
L = [int(input("For List 1, enter a number: ")) for i in range(random.randint(2, 5))]
L1 = [int(input("For List 2, enter a number: ")) for i in range(random.randint(2, 6))]
Upvotes: 1
Reputation: 383
I think what you want to do is to use a list comprehension with square brackets instead of curved brackets.
import random
L = [int(input("For List 1, enter a number: ")) for i in range(random.randint(2, 5))]
L1 = [int(input("For List 2, enter a number: ")) for i in range(random.randint(2, 6))]
common = []
for i in L:
if i in L1:
common.append(i)
print(common)
If you instead want to do a tuple comprehension, you could do it as follows:
import random
L = tuple(int(input("For List 1, enter a number: ")) for i in range(random.randint(2, 5)))
L1 = tuple(int(input("For List 2, enter a number: ")) for i in range(random.randint(2, 6)))
common = []
for i in L:
if i in L1:
common.append(i)
print(common)
Upvotes: 0