A new to Python question

Bengt Richter bokr at oz.net
Sat May 14 18:04:02 EDT 2005


On 14 May 2005 13:25:55 -0700, "M.E.Farmer" <mefjr75 at hotmail.com> wrote:

>I said exactly what I meant, the parentheses around the values creates
>a tuple that you have no reference to! It also has a side effect of
I don't understand what you are saying, or meaning ;-)
BTW, the function call has nothing to do with what happens on the left hand side
of the assignment. It is only the result of the function call that counts, so we
could as well use a literal or other expression. This is a matter of unpacking
a sequence according to the left hand target. E.g.,

 >>> iter([1,2,3])
 <listiterator object at 0x02F8F68C>
 >>> a,b,c = iter([1,2,3])
 >>> d,e,f = [1,2,3]
 >>> g,h,i = 'GHI'
 >>> [a,b,c,d,e,f,g,h,i]
 [1, 2, 3, 1, 2, 3, 'G', 'H', 'I']

Ok, now looking at the code for the assignment to a,b,c vs to (a,b,c):

 >>> import dis
 >>> dis.dis(compile('(a,b,c) = iter([1,2,3])','','exec'))
   1           0 LOAD_NAME                0 (iter)
               3 LOAD_CONST               0 (1)
               6 LOAD_CONST               1 (2)
               9 LOAD_CONST               2 (3)
              12 BUILD_LIST               3
              15 CALL_FUNCTION            1
              18 UNPACK_SEQUENCE          3
              21 STORE_NAME               1 (a)
              24 STORE_NAME               2 (b)
              27 STORE_NAME               3 (c)
              30 LOAD_CONST               3 (None)
              33 RETURN_VALUE
 >>> dis.dis(compile('a,b,c = iter([1,2,3])','','exec'))
   1           0 LOAD_NAME                0 (iter)
               3 LOAD_CONST               0 (1)
               6 LOAD_CONST               1 (2)
               9 LOAD_CONST               2 (3)
              12 BUILD_LIST               3
              15 CALL_FUNCTION            1
              18 UNPACK_SEQUENCE          3
              21 STORE_NAME               1 (a)
              24 STORE_NAME               2 (b)
              27 STORE_NAME               3 (c)
              30 LOAD_CONST               3 (None)
              33 RETURN_VALUE
 
I don't see anything in the code about creating a tuple that you have no reference to.
To see the unpacking of "GHI" so as to get rid of the function call red herring:

 >>> dis.dis(compile('a,b,c = "GHI"','','exec'))
   1           0 LOAD_CONST               0 ('GHI')
               3 UNPACK_SEQUENCE          3
               6 STORE_NAME               0 (a)
               9 STORE_NAME               1 (b)
              12 STORE_NAME               2 (c)
              15 LOAD_CONST               1 (None)
              18 RETURN_VALUE
 >>> dis.dis(compile('(a,b,c) = "GHI"','','exec'))
   1           0 LOAD_CONST               0 ('GHI')
               3 UNPACK_SEQUENCE          3
               6 STORE_NAME               0 (a)
               9 STORE_NAME               1 (b)
              12 STORE_NAME               2 (c)
              15 LOAD_CONST               1 (None)
              18 RETURN_VALUE

ISTM the assignment part starts with UNPACK_SEQUENCE and all the code looks the same.
BTW, UIAM it is the commas that define tuples, so the outermost parens are really expression
parens more than tuple syntax. But note that you can have nested tuple structure as target,
and that does change the unpacking code (and what it expects to have available to unpack):

 >>> (x,(y,z)) = 'XYZ'
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 ValueError: too many values to unpack
 >>> (x,(y,z)) = 'X','YZ'
 >>> x
 'X'
 >>> y
 'Y'
 >>> z
 'Z'
 >>> (x,(y,z)) = [1, [2,3]]
 >>> x
 1
 >>> y
 2
 >>> z
 3
 >>> dis.dis(compile('(x,(y,z)) = 0','','exec'))
   1           0 LOAD_CONST               0 (0)
               3 UNPACK_SEQUENCE          2
               6 STORE_NAME               0 (x)
               9 UNPACK_SEQUENCE          2
              12 STORE_NAME               1 (y)
              15 STORE_NAME               2 (z)
              18 LOAD_CONST               1 (None)
              21 RETURN_VALUE

Obviously we can't unpack the zero, but the code doesn't know
that until it tries it, so we can look at what the left hand side code is
independent of the right hand side.


>binding the names inside the tuple to a value and placing them in the
>local namespace( implicit tuple unpacking ). It might be the "same" as
>no parens but it isn't very clear. If you want a tuple make it
>explicit, if you want individual names make it explicit.
OTOH, you might want a mix:

 >>> a, tup, (b,c), d = ['A', ('a', 'tuple'), 'BC', 'Sandra']
 >>> a
 'A'
 >>> tup
 ('a', 'tuple')
 >>> b
 'B'
 >>> c
 'C'
 >>> d
 'Sandra'

Or with gratuitous _outer_ parens:

 >>> (a, tup, (b,c), d) = ['A', ('a', 'tuple'), 'BC', 'Sandra']
 >>> a
 'A'
 >>> tup
 ('a', 'tuple')
 >>> b
 'B'
 >>> c
 'C'
 >>> d
 'Sandra'

 >>> dis.dis(compile("a, tup, (b,c), d = ['A', ('a', 'tuple'), 'BC', 'Sandra']",'','exec'))
   1           0 LOAD_CONST               0 ('A')
               3 LOAD_CONST               6 (('a', 'tuple'))
               6 LOAD_CONST               3 ('BC')
               9 LOAD_CONST               4 ('Sandra')
              12 BUILD_LIST               4
              15 UNPACK_SEQUENCE          4
              18 STORE_NAME               0 (a)
              21 STORE_NAME               1 (tup)
              24 UNPACK_SEQUENCE          2
              27 STORE_NAME               2 (b)
              30 STORE_NAME               3 (c)
              33 STORE_NAME               4 (d)
              36 LOAD_CONST               5 (None)
              39 RETURN_VALUE

Regards,
Bengt Richter



More information about the Python-list mailing list