As we all know, there's list comprehension, like
[i for i in [1, 2, 3, 4]]
and there is dictionary comprehension, like
{i:j for i, j in {1: 'a', 2: 'b'}.items()}
but
(i for i in (1, 2, 3))
will end up in a generator, not a tuple
comprehension. Why is that?
My guess is that a tuple
is immutable, but this does not seem to be the answer.
You can use a generator expression:
tuple(i for i in (1, 2, 3))
but parentheses were already taken for … generator expressions.
Raymond Hettinger (one of the Python core developers) had this to say about tuples in a recent tweet:
#python tip:Generally, lists are for looping; tuples for structs. Lists are homogeneous; tuples heterogeneous.Lists for variable length.
This (to me) supports the idea that if the items in a sequence are related enough to be generated by a, well, generator, then it should be a list. Although a tuple is iterable and seems like simply a immutable list, it's really the Python equivalent of a C struct:
struct {
int a;
char b;
float c;
} foo;
struct foo x = { 3, 'g', 5.9 };
becomes in Python
x = (3, 'g', 5.9)
Since Python 3.5, you can also use splat *
unpacking syntax to unpack a generator expresion:
*(x for x in range(10)),
Comprehension works by looping or iterating over items and assigning them into a container, a Tuple is unable to receive assignments.
Once a Tuple is created, it can not be appended to, extended, or assigned to. The only way to modify a Tuple is if one of its objects can itself be assigned to (is a non-tuple container). Because the Tuple is only holding a reference to that kind of object.
Also - a tuple has its own constructor tuple()
which you can give any iterator. Which means that to create a tuple, you could do:
tuple(i for i in (1,2,3))
As another poster macm
mentioned , the fastest way to create a tuple from a generator is tuple([generator])
.
Performance Comparison
List comprehension:
$ python3 -m timeit "a = [i for i in range(1000)]" 10000 loops, best of 3: 27.4 usec per loop
Tuple from list comprehension:
$ python3 -m timeit "a = tuple([i for i in range(1000)])" 10000 loops, best of 3: 30.2 usec per loop
Tuple from generator:
$ python3 -m timeit "a = tuple(i for i in range(1000))" 10000 loops, best of 3: 50.4 usec per loop
Tuple from unpacking:
$ python3 -m timeit "a = *(i for i in range(1000))," 10000 loops, best of 3: 52.7 usec per loop
My version of python:
$ python3 --version
Python 3.6.3
So you should always create a tuple from a list comprehension unless performance is not an issue.
My best guess is that they ran out of brackets and didn't think it would be useful enough to warrent adding an "ugly" syntax ...
Tuples cannot efficiently be appended like a list.
So a tuple comprehension would need to use a list internally and then convert to a tuple.
That would be the same as what you do now : tuple( [ comprehension ] )
Parentheses do not create a tuple. aka one = (two) is not a tuple. The only way around is either one = (two,) or one = tuple(two). So a solution is:
tuple(i for i in myothertupleorlistordict)
I believe it's simply for the sake of clarity, we do not want to clutter the language with too many different symbols. Also a tuple
comprehension is never necessary, a list can just be used instead with negligible speed differences, unlike a dict comprehension as opposed to a list comprehension.
We can generate tuples from a list comprehension. The following one adds two numbers sequentially into a tuple and gives a list from numbers 0-9.
>>> print k
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> r= [tuple(k[i:i+2]) for i in xrange(10) if not i%2]
>>> print r
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
来源:https://stackoverflow.com/questions/16940293/why-is-there-no-tuple-comprehension-in-python