Reputation: 399
I am going through the exercises of this site https://anandology.com/python-practice-book/working-with-data.html when I tried to recreate the zip function through list comprehension. Now I created this function. But instead of getting a list I get a generator :-(
def zipp (liste1,liste2):
length= len(liste1)
zipped=[]
[zipped.append(tuple(liste1[i], liste2[i]) for i in range(length))]
return zipped
I searched a little in here and found this: Python: why does list comprehension produce a generator?
Accordingly I used the "tuple" statement already but to no awail.
I have no idea why I get a generator even with the tuple() inserted. So my questions:
Thanks.
edit: The result I expect is list of tuple with member of each list in it. This I what I should get:
zipp([1, 2, 3], ["a", "b", "c"]) -> [(1, "a"), (2, "b"), (3, "c")]
Upvotes: 2
Views: 425
Reputation: 868
trying to answer your questions...
1.- why?
A: As many have mention, you return the zipped
list as a list generators within the list comprehension [zipped.append(tuple(liste1[i], liste2[i]) for i in range(length))]
, not a nice way of doing by the way. that's why you get those generators.
2.- What do I need to change or where can I read/hear more to get "enlightened" myself?
A: If you still want to do that way, you only have to append the two items, by moving the parenthesis and removing the tuple function, like so:
def zipp (liste1, liste2):
length = len(liste1)
zipped = []
[zipped.append( (liste1[i], liste2[i]) ) for i in range(length) ] # not the best way, but still works. This created list is never used.
return zipped
then it's possible to return the list
zipp([1,2,3], ['a','b','c'])
Note that this asumes both list have same length. Otherwise you have to choose one (like you are doing) or finding the minimum of both lengths (it's also posible to choose the longest and fill with whatever it's needed):
min(len(liste1), len(liste2))
3.- How could I use the generator to get the result?
A: For it to be a generator you need to yield the nedeed value:
def zipp2 (liste1,liste2):
i = 0
minval = min(len(liste1), len(liste2))
while i< minval:
yield (liste1[i], liste2[i])
i += 1
# call the function generator
gen = zipp2([1,2,3], ['a','b','c'])
print(gen)
for p in gen:
print(p)
and get the results...
<generator object zipp2 at 0x7fe46bef3db0>
(1, 'a')
(2, 'b')
(3, 'c')
Upvotes: 1
Reputation: 140178
you're putting a generator in your object:
tuple(liste1[i], liste2[i]) for i in range(length)
(and tuple
doesn't work too, just remove it....)
(and don't use comprehensions for side effects)
The best way would be to rewrite it completely using a list comprehension which actually returns something, as list comprehensions are supposed to, taking the min of both lengths to fully emulate zip
:
def zipp (liste1,liste2):
return [(liste1[i], liste2[i]) for i in range(min(len(liste1),len(liste2)))]
classic loop version (no comprehensions)
def zipp (liste1,liste2):
result = []
for i in range(min(len(liste1),len(liste2))):
result.append((liste1[i], liste2[i]))
return result
of course this is nothing else than list(zip(liste1,liste2))
(forcing iteration on zip
)
Upvotes: 2