[Tutor] why can you swap an immutable tuple?
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?
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?
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?
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?
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?
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?
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?
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?
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