What is the difference between "()" and "[]" when creating in Python?

There is a list: nodes = [20, 21, 22, 23, 24, 25].

I used two ways to create new 2-dimensional objects:

tour1 = (((a,b) for a in nodes )for b in nodes) tour2 = [[(a,b) for a in nodes ]for b in nodes] 

Type of tour1 is a generator, and tour2 is a list:

 In [34]: type(tour1) Out[34]: <type 'generator'> In [35]: type(tour2) Out[35]: <type 'list'> 

I want to know why tour1 is not a tuple? Thanks.

+7
source share
5 answers

The main difference is that the first is an expression of the generator, and the second is the understanding of the list. The former only give elements as needed, while the latter always gives the entire list when understanding is performed.

See Generator Expressions and Understanding Lists for more information.

In Python, there is no concept of a "tuple", which is what you expect from the first syntax.

If you want to turn tour1 into a tuple of tuples, you can use the following:

 In [89]: tour1 = tuple(tuple((a,b) for a in nodes )for b in nodes) In [90]: tour1 Out[90]: (((20, 20), (21, 20), (22, 20), (23, 20), (24, 20), (25, 20)), ((20, 21), (21, 21), (22, 21), (23, 21), (24, 21), (25, 21)), ((20, 22), (21, 22), (22, 22), (23, 22), (24, 22), (25, 22)), ((20, 23), (21, 23), (22, 23), (23, 23), (24, 23), (25, 23)), ((20, 24), (21, 24), (22, 24), (23, 24), (24, 24), (25, 24)), ((20, 25), (21, 25), (22, 25), (23, 25), (24, 25), (25, 25))) 
+10
source

The tuple syntax is not parentheses () , it is a comma,. You can create a tuple without parentheses:

 x = 1, 2, 3 

If you want to create a tuple from understanding, just use the tuple constructor:

 tuple(tuple((a,b) for a in nodes )for b in nodes) 
+10
source

Since the syntax (x for x in l) is the so-called "generator expression": see http://docs.python.org/2/reference/expressions.html#generator-expressions

+5
source

This generator, but you can just change it to a tuple:

 >>> (i for i in xrange(4)) <generator object <genexpr> at 0x23ea9b0> >>> tuple(i for i in xrange(4)) (0, 1, 2, 3) 
+2
source

To add ... Actually, the generator expression does not need parentheses at all. You only need them when the generator expression creates the wrong syntax - here because of purpose. When passing a generator to a function (or the like) you don't need parentheses. Try the following:

 tour3 = list(list((a,b) for a in nodes) for b in nodes) 

It produces exactly the same result as your tour2 . So you can look [ as syntactic sugar for list( , and ] is the syntactic sugar associated with ) . However, the compiler compiles differently. You can try disassembling (you need to pass a function):

 >>> import dis >>> def fn1(): ... return list(list((a,b) for a in nodes) for b in nodes) ... >>> def fn2(): ... return [[(a,b) for a in nodes ]for b in nodes] ... >>> dis.dis(fn1) 2 0 LOAD_GLOBAL 0 (list) 3 LOAD_CONST 1 (<code object <genexpr> at 000000000229A9B0, file "<stdin>", line 2>) 6 MAKE_FUNCTION 0 9 LOAD_GLOBAL 1 (nodes) 12 GET_ITER 13 CALL_FUNCTION 1 16 CALL_FUNCTION 1 19 RETURN_VALUE >>> dis.dis(fn2) 2 0 BUILD_LIST 0 3 LOAD_GLOBAL 0 (nodes) 6 GET_ITER >> 7 FOR_ITER 37 (to 47) 10 STORE_FAST 0 (b) 13 BUILD_LIST 0 16 LOAD_GLOBAL 0 (nodes) 19 GET_ITER >> 20 FOR_ITER 18 (to 41) 23 STORE_FAST 1 (a) 26 LOAD_FAST 1 (a) 29 LOAD_FAST 0 (b) 32 BUILD_TUPLE 2 35 LIST_APPEND 2 38 JUMP_ABSOLUTE 20 >> 41 LIST_APPEND 2 44 JUMP_ABSOLUTE 7 >> 47 RETURN_VALUE 

So you can see that it is different (i.e. it looks like syntactic sugar, but it is not). Unfortunately, Python cannot parse the generator:

 >>> g = (list((a,b) for a in nodes) for b in nodes) >>> dis.dis(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python27\lib\dis.py", line 49, in dis type(x).__name__ TypeError: don't know how to disassemble generator objects 

Update:

You can tempt - when viewing the above parsed code - fn1 works faster (having a shorter code). However, this applies to all function calls in all languages ​​that the function call looks shorter than the deployed code. It does not say anything about the internals of the called code. Some points of Zen Python:

 >>> import this The Zen of Python, by Tim Peters ... Readability counts. ... In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. ... >>> 

There is a standard timeit module for measuring runtime. Let's try to use it for two cases:

 >>> import timeit >>> t = timeit.Timer('list(list((a,b) for a in nodes) for b in nodes)', ... 'nodes = [20, 21, 22, 23, 24, 25]') >>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)) 17.74 usec/pass 

and now with square brackets:

 >>> t = timeit.Timer('[[(a,b) for a in nodes ]for b in nodes]', ... 'nodes = [20, 21, 22, 23, 24, 25]') >>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)) 7.14 usec/pass >>> 

This clearly shows that making a list of lists via [ ] faster. The reason is that fewer function calls. The Python compiler can create simpler code.

+2
source

All Articles