[Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Jim Mooney
I thought tuples were immutable but it seems you can swap them, so I'm
confused:

a,b = 5,8

print a  # result 5

a,b = b,a

print a  # result 8, so they swapped

# but if I test the type of a,b I get a tuple

testit = a,b
print type(testit)  #comes out as a tuple

print testit, # result is (8,5)

# So how am I swapping elements of a tuple when a tuple is immutable?

#t rying so change a tuple since I just did it

testit[1] = 14  #program crashes - *TypeError: 'tuple' object does not
support item assignment *so the tuple I just changed is indeed immutable

-- 
Jim Mooney

Coding? You can get a woman to do that! he said with a sneer. --heard
from a physics professor in 1969
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Mark Lawrence

On 25/05/2013 19:56, Jim Mooney wrote:

I thought tuples were immutable but it seems you can swap them, so I'm
confused:

a,b = 5,8


You've defined two names a and b so where's the tuple?



print a  # result 5

a,b = b,a


You've redefined two names a and b to take the values that were held in 
b and a so still no tuple.




print a  # result 8, so they swapped

# but if I test the type of a,b I get a tuple

testit = a,b


Finally a tuple.


print type(testit)  #comes out as a tuple

print testit, # result is (8,5)

# So how am I swapping elements of a tuple when a tuple is immutable?

#t rying so change a tuple since I just did it

testit[1] = 14  #program crashes - *TypeError: 'tuple' object does not
support item assignment *so the tuple I just changed is indeed immutable


Exactly as expected.  So what precisely don't you understand?



--
Jim Mooney

Coding? You can get a woman to do that! he said with a sneer. --heard
from a physics professor in 1969


--
If you're using GoogleCrap™ please read this 
http://wiki.python.org/moin/GoogleGroupsPython.


Mark Lawrence

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Steve Willoughby

On 2013-5月-25, at 上午11:56, Jim Mooney wrote:

 I thought tuples were immutable but it seems you can swap them, so I'm 
 confused:
 
 a,b = 5,8
 


I think you're confusing mutating the tuples with assigning the immutable 
tuples different names.  The variable names are just labels you attach to them. 
 The tuple values themselves cannot change.  

That said, your example here isn't a tuple but a pair of singleton values. 

If you said 
tuple1 = 1,2,3,4
tuple2 = 5,6,7,8

you create two tuples which are, yes, immutable.  They happen to be called 
tuple1 and tuple2 but that's beside the point of immutability.  If you pass 
them to a function, they'll be known locally there under different names but 
they're still immutable tuples.

Does that help?
--steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Dave Angel

On 05/25/2013 02:56 PM, Jim Mooney wrote:

I thought tuples were immutable but it seems you can swap them, so I'm
confused:



The anonymous tuple object is immutable, but you just build one 
temporarily, extract both items from it, and destroy it.



a,b = 5,8



The a,b on the left hand side is a tuple-unpacking-syntax, where it 
takes whatever tuple (or list, or whatever else supports the protocol), 
and extracts the elements in order.  a,b are not tied together in any sense.



print a  # result 5

a,b = b,a



Here you build another anonymous tuple that happens to be in the reverse 
order as the earlier one.  Then you unpack it into two arbitrary 
variables, that only happen to be the same ones as you used before, and 
only happens to be the same ones as used on the right side.



print a  # result 8, so they swapped

# but if I test the type of a,b I get a tuple

testit = a,b
print type(testit)  #comes out as a tuple


Now you're building yet another tuple, and actually binding a name to 
it.  So it won't go away at the end of the statement.




print testit, # result is (8,5)

# So how am I swapping elements of a tuple when a tuple is immutable?

#t rying so change a tuple since I just did it

testit[1] = 14  #program crashes - *TypeError: 'tuple' object does not
support item assignment *so the tuple I just changed is indeed immutable



This time you ARE trying to change a tuple, for the first time.


--
DaveA
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread David
On 26/05/2013, Jim Mooney cybervigila...@gmail.com wrote:
 I thought tuples were immutable but it seems you can swap them, so I'm
 confused:

 a,b = 5,8

I think your confusion might arise from not understanding that the
meaning of the comma differs depending on whether it is on the left or
the right side of an equals sign.

On the right: it combines the 5 and the 8 to create a tuple, as yet un-named.

On the left: it says to unpack the tuple-on-the-right into two
independent values and assign them to the names a and b. So here it is
effectively a=5 and b=8.

So, there is no tuple on the left hand side. The statement does not
create a tuple, because the comma on the left side means unpack the
tuple-on-the-right.

To assign a name to a tuple, there must be no comma on the left side, like this:
name_of_tuple = 5, 8
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Steven D'Aprano

On 26/05/13 05:23, Mark Lawrence wrote:

On 25/05/2013 19:56, Jim Mooney wrote:

I thought tuples were immutable but it seems you can swap them, so I'm
confused:

a,b = 5,8


You've defined two names a and b so where's the tuple?


On the right hand side, 5,8 creates a tuple, which is then immediately unpacked 
to two individual values. You can see this by disassembling the code. In 2.7, 
you get this:

py from dis import dis
py code = compile(a, b = 5, 8, , exec)
py dis(code)
  1   0 LOAD_CONST   3 ((5, 8))
  3 UNPACK_SEQUENCE  2
  6 STORE_NAME   0 (a)
  9 STORE_NAME   1 (b)
 12 LOAD_CONST   2 (None)
 15 RETURN_VALUE


Other versions may be slightly different, for example in Python 1.5 (ancient 
history!) the constant tuple (5, 8) is not created at compile-time, but at 
run-time:

# output of dis from Python 1.5:

  0 SET_LINENO  0
  3 SET_LINENO  1
  6 LOAD_CONST  0 (5)
  9 LOAD_CONST  1 (8)
 12 BUILD_TUPLE 2
 15 UNPACK_TUPLE2
 18 STORE_NAME  0 (a)
 21 STORE_NAME  1 (b)
 24 LOAD_CONST  2 (None)
 27 RETURN_VALUE


But whenever it is created, the right hand side creates a tuple.

An interesting fact: on the left hand side, Python is very flexible with its 
sequence unpacking syntax. All of these are equivalent, where RHS (Right Hand 
Side) evaluates to exactly two items:

a, b = RHS
(a, b) = RHS
[a, b] = RHS


Note also that it is *sequence* unpacking, not *tuple* unpacking. Any sequence 
will work. Actually, any iterable object will work, not just sequences. But the 
name comes from way back in early Python days when it only worked on sequences.



--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Jim Mooney
On 25 May 2013 18:34, David bouncingc...@gmail.com wrote:

 On 26/05/2013, Jim Mooney cybervigila...@gmail.com wrote:
  I thought tuples were immutable but it seems you can swap them, so I'm
  confused:
 
  a,b = 5,8

 I think your confusion might arise from not understanding that the
 meaning of the comma differs depending on whether it is on the left or
 the right side of an equals sign.


I think the problem is the book I'm reading, which never mentions
unpacking, so I thought from hearing a comma creates a tuple, that it was
tuples on both sides  ;')  I'm reading Learning Computer Science With
Python and I think it's scanting the Python-detail to get on with the
CompSci. I'll go look for something more PyDetailed ;')
-- 
Jim Mooney

Coding? A woman can do that! he sneered --heard from a physics professor
in 1969
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread Jim Mooney
On 25 May 2013 19:38, Steven D'Aprano st...@pearwood.info wrote:

 On 26/05/13 05:23, Mark Lawrence wrote:



 On the right hand side, 5,8 creates a tuple, which is then immediately
 unpacked to two individual values. You can see this by disassembling the
 code. In 2.7, you get this:

 py from dis import dis
 py code = compile(a, b = 5, 8, , exec)
 py dis(code)
   1   0 LOAD_CONST   3 ((5, 8))
   3 UNPACK_SEQUENCE  2
   6 STORE_NAME   0 (a)
   9 STORE_NAME   1 (b)
  12 LOAD_CONST   2 (None)
  15 RETURN_VALUE

 That disassembling looks like it could clarify a number of things. I'll
have to try it. It might make more sense to me since my  only programming,
besides a bit of javascript copy-hacking for websites, was A86 Assembler,
some decades ago, when I wrote an ASCII Art prog for Fidonet.

Then I got into other fields entirely to make a living. But Asm actually
makes sense to me and the disassemble looks close to it. (I can't count the
times I wiped out DOS and had to reload it ;')  A86 had a wonderful macro
language, though.

Jim
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] why can you swap an immutable tuple?

2013-05-25 Thread eryksun
On Sat, May 25, 2013 at 10:38 PM, Steven D'Aprano st...@pearwood.info wrote:
 On 26/05/13 05:23, Mark Lawrence wrote:

 On 25/05/2013 19:56, Jim Mooney wrote:

 I thought tuples were immutable but it seems you can swap them, so I'm
 confused:

 a,b = 5,8


 You've defined two names a and b so where's the tuple?


 On the right hand side, 5,8 creates a tuple, which is then immediately
 unpacked to two individual values. You can see this by disassembling the
 code. In 2.7, you get this:

The abstract source tree (AST) uses a tuple or list for sequences in
targets (multiple targets are generated for chained assignment) and
also for the value. The tuples and lists for the target(s) obviously
aren't preserved in the source code. They guide the compiler in the
arrangement of UNPACK_SEQUENCE and STORE operations.

A BUILD_TUPLE / BUILD_LIST operation for the right-hand side is
generally preserved for the value tuple or list. One optimization in
CPython, as you've shown, is to store a tuple of constants in the code
object.

Also, if the length of the sequence is less than 4, CPython's peephole
optimizer will replace the BUILD/UNPACK with simple stack rotation(s).
For length 2 it replaces it with a ROT_TWO. For length 3 it uses a
ROT_THREE followed by a ROT_TWO. For example:

def f():
  a,b,c = x,y,z

 dis.dis(f)
  2   0 LOAD_GLOBAL  0 (x)
  3 LOAD_GLOBAL  1 (y)
  6 LOAD_GLOBAL  2 (z)
  9 ROT_THREE
 10 ROT_TWO
 11 STORE_FAST   0 (a)
 14 STORE_FAST   1 (b)
 17 STORE_FAST   2 (c)
 20 LOAD_CONST   0 (None)
 23 RETURN_VALUE

In the original bytecode, before the optimization, there was a
BUILD_TUPLE(3) followed immediately by UNPACK_SEQUENCE(3). The LOAD
operations set the stack as [x,y,z], where z is at the top of the
stack, which sets up for BUILD_TUPLE. But UNPACK_SEQUENCE would unpack
in reverse, leaving the stack as [z,y,x] to be popped off into the
names a, b, and c. So the optimizer inserts a ROT_THREE to get [x,y,z]
= [z,x,y] and then ROT_TWO to get [z,x,y] = [z,y,x].

 An interesting fact: on the left hand side, Python is very flexible with its
 sequence unpacking syntax. All of these are equivalent, where RHS (Right
 Hand Side) evaluates to exactly two items:

Unpacking in assignment allows an almost comical level of complexity,
not even including subscription and attribute targets that can use
expressions for the primary object and subscript. A 'simple' example:

def f(arg):
i0,(i1,i2),(i3,(i4,i5,i6)) = arg
return i0,i1,i2,i3,i4,i5,i6

 f([0,'ab',[1,'cde']])
(0, 'a', 'b', 1, 'c', 'd', 'e')

Here's the AST for this silliness:

 src = 'i0,(i1,i2),(i3,(i4,i5,i6)) = arg'
 ast.dump(ast.parse(src).body[0])

I formatted the output a bit:

Assign(
  targets=[
Tuple(
  elts=[
Name(id='i0', ctx=Store()),
Tuple(
  elts=[
Name(id='i1', ctx=Store()),
Name(id='i2', ctx=Store())],
  ctx=Store()),
Tuple(
  elts=[
Name(id='i3', ctx=Store()),
Tuple(
  elts=[
Name(id='i4', ctx=Store()),
Name(id='i5', ctx=Store()),
Name(id='i6', ctx=Store())],
  ctx=Store())],
  ctx=Store())],
  ctx=Store())],
  value=Name(id='arg', ctx=Load()))
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor