I just read the question Why is there no tuple comprehension in Python?
In the comments of the accepted answer, it is stated that there are no true "tuple comprehensions". Instead, our current option is to use a generator expression and pass the resulting generator object to the tuple constructor:
tuple(thing for thing in things)
Alternatively, we can create a list using a list comprehension and then pass the list to the tuple constructor:
tuple([thing for thing in things])
Lastly and to the contrary of the accepted answer, a more recent answer stated that tuple comprehensions are indeed a thing (since Python 3.5) using the following syntax:
*(thing for thing in things),
To me, it seems like the second example is also one where a generator object is created first. Is this correct?
Is there any difference between these expressions in terms of what goes on behind the scenes? In terms of performance? I assume the first and third could have latency issues while the second could have memory issues (as is discussed in the linked comments).
- Comparing the first one and the last, which one is more pythonic?
Update:
As expected, the list comprehension is indeed much faster. I don't understand why the first one is faster than the third one however. Any thoughts?
>>> from timeit import timeit
>>> a = 'tuple(i for i in range(10000))'
>>> b = 'tuple([i for i in range(10000)])'
>>> c = '*(i for i in range(10000)),'
>>> print('A:', timeit(a, number=1000000))
>>> print('B:', timeit(b, number=1000000))
>>> print('C:', timeit(c, number=1000000))
A: 438.98362647295824
B: 271.7554752581845
C: 455.59842588083677
%timeit
in ipython. Find out which is better on your specific machine. – Bludgeonx for y in z
in the list comprehension may look like a generator, but it isn't. The inner workings are different. E.g. aStopIteration
raised in thex
part will stop a generator but will bubble out of the list comprehension. – Nestax for x in y
and notx for y in z
. With regards to the other points raised here, I agree with you all. – Abfarad