Hi I'm trying to teach myself python and so far to good, but I'm having
a bit of trouble getting a function to work the way I think it should
work. Right now I'm taking a simple program I wrote in Fortran and
trying to do it in Python. I got it to work, but now I'm trying to
modularize it. My fortran program uses a subroutine and I was trying
to do the same thing in Python. But I'm still new so I'm having
trouble understanding what I'm doing wrong. Here is my code:
#! /usr/bin/python
#This program takes two vectors and multiplies them
#against a 10X10 array. It also then gives the dot product,
#sum, and max value of the array.
import Numeric
def abc(array1,array2,dotprod,sum,maxvalue):
"""Takes two arrays and performs predetermined calculations,
Then returns the solutions back as the same array, along
with the dot product, sum, and max value of the array."""
#TODO: Get this damn thing working!!
print "Array 1 in:",array1 #Debug
data = Numeric.zeros((10,10))
for i in range(10):
for j in range(10):
data[i,j] = (i+1)+(j+1)
e = Numeric.matrixmultiply(data, array1)
g = Numeric.matrixmultiply(Numeric.transpose(data),arr ay2)
array1 = e
array2 = g
dotprod = Numeric.dot(array1,array2)
sum = Numeric.sum(array1)
maxvalue = array2[Numeric.argmax(array2)]
print "Array 1 out:",array1 #Debug
return array1,array2,dotprod,sum,maxvalue #<<-- Not working as I
thought it would.
x = Numeric.arange(1,11)
y = Numeric.arange(1,11)*2
dotp,sumx,maxv = 0,0,0 #Is this the only way to declare a variable?
print 'Array X:',x
print 'Array Y:',y
abc(x,y,dotp,sumx,maxv)
print 'Calling function abc'
print 'Array X:',x
print 'Array Y:',y
print 'Dot Product of X and Y:',dotp
print 'Sum of array X:',sumx
print 'Max value of array Y:',maxv
If you run it the data gets passed to the function just fine and it
finds the right numbers. Its just getting it to pass them back thats
not working. I put some print statements inside the function just to
see how the data gets passed. So any ideas that would help me? If you
want to see the fortran code just email me.
David 32 2418
On 2005-05-14, David wrote: abc(x,y,dotp,sumx,maxv)
(x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv)
Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Hi,
You're thinking you're passing the arguments as reference (look at mutable
vs non-mutable)
Your function returns the values in a tupple (x,y,...); you need to fetch
the values from that tupple
Regards,
Philippe
David wrote: Hi I'm trying to teach myself python and so far to good, but I'm having a bit of trouble getting a function to work the way I think it should work. Right now I'm taking a simple program I wrote in Fortran and trying to do it in Python. I got it to work, but now I'm trying to modularize it. My fortran program uses a subroutine and I was trying to do the same thing in Python. But I'm still new so I'm having trouble understanding what I'm doing wrong. Here is my code:
#! /usr/bin/python #This program takes two vectors and multiplies them #against a 10X10 array. It also then gives the dot product, #sum, and max value of the array.
import Numeric def abc(array1,array2,dotprod,sum,maxvalue): """Takes two arrays and performs predetermined calculations, Then returns the solutions back as the same array, along with the dot product, sum, and max value of the array.""" #TODO: Get this damn thing working!! print "Array 1 in:",array1 #Debug data = Numeric.zeros((10,10)) for i in range(10): for j in range(10): data[i,j] = (i+1)+(j+1)
e = Numeric.matrixmultiply(data, array1) g = Numeric.matrixmultiply(Numeric.transpose(data),arr ay2) array1 = e array2 = g dotprod = Numeric.dot(array1,array2) sum = Numeric.sum(array1) maxvalue = array2[Numeric.argmax(array2)] print "Array 1 out:",array1 #Debug
return array1,array2,dotprod,sum,maxvalue #<<-- Not working as I thought it would.
x = Numeric.arange(1,11) y = Numeric.arange(1,11)*2 dotp,sumx,maxv = 0,0,0 #Is this the only way to declare a variable?
print 'Array X:',x print 'Array Y:',y abc(x,y,dotp,sumx,maxv) print 'Calling function abc' print 'Array X:',x print 'Array Y:',y print 'Dot Product of X and Y:',dotp print 'Sum of array X:',sumx print 'Max value of array Y:',maxv
If you run it the data gets passed to the function just fine and it finds the right numbers. Its just getting it to pass them back thats not working. I put some print statements inside the function just to see how the data gets passed. So any ideas that would help me? If you want to see the fortran code just email me.
David
On 2005-05-14, Philippe C. Martin wrote: You're thinking you're passing the arguments as reference
That is the way Fortran handles them:
[...] Right now I'm taking a simple program I wrote in Fortran
Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
David wrote: Hi I'm trying to teach myself python and so far to good, but I'm
having a bit of trouble getting a function to work the way I think it should work. Right now I'm taking a simple program I wrote in Fortran and trying to do it in Python. I got it to work, but now I'm trying to modularize it. My fortran program uses a subroutine and I was trying to do the same thing in Python. But I'm still new so I'm having trouble understanding what I'm doing wrong. Here is my code:
#! /usr/bin/python #This program takes two vectors and multiplies them #against a 10X10 array. It also then gives the dot product, #sum, and max value of the array.
import Numeric def abc(array1,array2,dotprod,sum,maxvalue): """Takes two arrays and performs predetermined calculations, Then returns the solutions back as the same array, along with the dot product, sum, and max value of the array.""" #TODO: Get this damn thing working!! print "Array 1 in:",array1 #Debug data = Numeric.zeros((10,10)) for i in range(10): for j in range(10): data[i,j] = (i+1)+(j+1)
e = Numeric.matrixmultiply(data, array1) g = Numeric.matrixmultiply(Numeric.transpose(data),arr ay2) array1 = e array2 = g dotprod = Numeric.dot(array1,array2) sum = Numeric.sum(array1) maxvalue = array2[Numeric.argmax(array2)] print "Array 1 out:",array1 #Debug
return array1,array2,dotprod,sum,maxvalue #<<-- Not working as I thought it would.
x = Numeric.arange(1,11) y = Numeric.arange(1,11)*2 dotp,sumx,maxv = 0,0,0 #Is this the only way to declare a variable?
print 'Array X:',x print 'Array Y:',y abc(x,y,dotp,sumx,maxv) print 'Calling function abc' print 'Array X:',x print 'Array Y:',y print 'Dot Product of X and Y:',dotp print 'Sum of array X:',sumx print 'Max value of array Y:',maxv
If you run it the data gets passed to the function just fine and it finds the right numbers. Its just getting it to pass them back thats not working. I put some print statements inside the function just to see how the data gets passed. So any ideas that would help me? If
you want to see the fortran code just email me.
David
Hello David,
welcome to Python!
Python always returns 'something' from a function or method if nothing
is specified or there is no return you get an implicit None.
You have created a function that accepts a few arguments and processes
them then returns there value.
The problem is that you **have not** used the return values ;)
example:
def funk(first,second,third):
return first,second,third
This can be like this:
print funk("theses three args can be anything",2,"three")
If you need to use the return values you need to assign them to a
"name" so you have a handle on them.
Variables are don't exist in Python there are only objects and names(
hence namespaces ), but not everyone is so strict and you still see
mention of 'variables' when they mean 'names'. ##dotp,sumx,maxv = 0,0,0 # not needed here print 'Array X:',x print 'Array Y:',y ## Notice we assign the return values to names so we can access it
later arr1,arr2,dotp,sumx,maxv = abc(x,y,0,0,0) print 'Calling function abc' print 'Array X:',arr1 print 'Array Y:',arr2 print 'Dot Product of X and Y:',dotp print 'Sum of array X:',sumx print 'Max value of array Y:',maxv
Or you could pack all return values into a tuple and access it thru
slices. ##dotp,sumx,maxv = 0,0,0 # not needed here print 'Array X:',x print 'Array Y:',y abcinfo = abc(x,y,0,0,0) print 'Calling function abc' print 'Array X:',abcinfo[0] print 'Array Y:',abcinfo[1] print 'Dot Product of X and Y:',abcinfo[2] print 'Sum of array X:',abcinfo[3] print 'Max value of array Y:',abcinfo[4]
Or you could use a dictionary, or etc...
The possibilities are endless.
Be sure to study up on namespaces, it will ease your Python woes.
Namespaces are the most fundamental part of Python that new users don't
understand. Namespace mastery will take you far.
Just remember there are only two scopes local and global ;) http://docs.python.org
hth,
M.E.Farmer
(x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv)
This will only create a tuple in memory that has no name to reference
it by!
How would you access the returned value?
If you want a tuple you need to assign all the return vales to a single
name.
mytup = abc(x,y,dotp,sumx,maxv)
M.E.Farmer
M.E.Farmer wrote: (x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv) This will only create a tuple in memory that has no name to reference it by!
Huh? This binds the names "x", "y", "dotp", "sumx" and "maxv" to the
values returned by abc:
py> def abc(*args):
.... return args
....
py> (x,y,dotp,sumx,maxv) = abc(2,3,5,7,11)
py> x
2
py> y
3
py> dotp
5
py> sumx
7
py> maxv
11
Of course, the parentheses around x,y,dotp,sumx,maxv are unnecessary.
STeVe
Thank you very much. Tulpes are really neat now that I've looked at
them. So after just fixing it, I changed it up and I would like to
show it off now.
#! /usr/bin/python
#This program takes two vectors and multiplies them
#against a 10X10 array. It also then gives the dot product,
#sum, and max value of the array.
import Numeric
def abc(package):
"""Takes two arrays and performs predetermined calculations,
Then returns the solutions back as the same array, along
with the dot product, sum, and max value of the array.
Data slots:
0 - First Array
1 - Second Array
2 - Dot product
3 - Sum
4 - Max Value"""
f = Numeric.zeros((10,10))
for i in range(10):
for j in range(10):
f[i,j] = (i+1)+(j+1)
e = Numeric.matrixmultiply(f, package[0])
g = Numeric.matrixmultiply(Numeric.transpose(f),packag e[1])
package[0] = e
package[1] = g
package[2] = Numeric.dot(package[0],package[1])
package[3] = Numeric.sum(package[0])
package[4] = package[1][Numeric.argmax(package[1])]
return package
data = [Numeric.arange(1,11),Numeric.arange(1,11)*2,0,0,0]
#data = [Array X, Array Y, Dot product, Sum, Max Value]
print 'Array X:',data[0]
print 'Array Y:',data[1]
data = abc(data)
print 'Calling function abc'
print 'Array X:',data[0]
print 'Array Y:',data[1]
print 'Dot Product of X and Y:',data[2]
print 'Sum of array X:',data[3]
print 'Max value of array Y:',data[4]
I think its just wonderful now, but if you got any other suggestions,
Please do tell. Thanks everyone.
David
Hmm don't know what happened. I guess the formatting got all chewed up. On 2005-05-14, M.E.Farmer wrote:
(x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv) This will only create a tuple in memory that has no name to reference it by!
Maybe. But it does not seem to hurt. And I am not sure the tupel _is_
really created in that situation.
How would you access the returned value? If you want a tuple you need to assign all the return vales to a single name.
We do not want the tuple.
Python 2.3.5 (#1, Apr 28 2005, 12:14:04)
[GCC 3.4.3-20050110 (Gentoo Linux 3.4.3.20050110-r2,
ssp-3.4.3.20050110-0, pie-
on linux2
Type "help", "copyright", "credits" or "license" for more information. def foo(): ... return 1,2,3 ... (a,b,c)=foo() print a,b,c
1 2 3
works.
Of course, you can omit the ():
a,b,c=foo() print a,b,c
1 2 3
That makes no difference.
Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Yes, I gathered.
We all get our habits from somewhere :-)
Regards,
Philippe
Bernd Nawothnig wrote: On 2005-05-14, Philippe C. Martin wrote:
You're thinking you're passing the arguments as reference
That is the way Fortran handles them:
[...]
Right now I'm taking a simple program I wrote in Fortran
Bernd
David wrote: Thank you very much. Tulpes are really neat now that I've looked at them. So after just fixing it, I changed it up and I would like to show it off now.
#! /usr/bin/python #This program takes two vectors and multiplies them #against a 10X10 array. It also then gives the dot product, #sum, and max value of the array.
import Numeric def abc(package): """Takes two arrays and performs predetermined calculations, Then returns the solutions back as the same array, along with the dot product, sum, and max value of the array.
Data slots: 0 - First Array 1 - Second Array 2 - Dot product 3 - Sum 4 - Max Value""" f = Numeric.zeros((10,10)) for i in range(10): for j in range(10): f[i,j] = (i+1)+(j+1)
e = Numeric.matrixmultiply(f, package[0]) g = Numeric.matrixmultiply(Numeric.transpose(f),packag e[1]) package[0] = e package[1] = g package[2] = Numeric.dot(package[0],package[1]) package[3] = Numeric.sum(package[0]) package[4] = package[1][Numeric.argmax(package[1])] return package
data = [Numeric.arange(1,11),Numeric.arange(1,11)*2,0,0,0] #data = [Array X, Array Y, Dot product, Sum, Max Value]
print 'Array X:',data[0] print 'Array Y:',data[1]
data = abc(data)
print 'Calling function abc' print 'Array X:',data[0] print 'Array Y:',data[1] print 'Dot Product of X and Y:',data[2] print 'Sum of array X:',data[3] print 'Max value of array Y:',data[4]
I think its just wonderful now, but if you got any other suggestions, Please do tell. Thanks everyone.
It's still not very Pythonic. Don't bother putting outputs in the
argument list. There are some good use cases for doing so, but until
you've been writing Python code for a while and the Pythonic idioms come
naturally to you, you should probably resist the urge. Python is not
Fortran.
def abc(x, y):
...
e = Numeric.matrixmultiply(f, x)
g = Numeric.matrixmultiply(Numeric.transpose(f), y)
dotp = Numeric.dot(x, y)
sumx = Numeric.sum(x)
maxy = Numeric.maximum.reduce(y)
return e, g, dotp, sumx, maxy
x = Numeric.arange(1,11)
y = x*2
x, y, dotp, sumx, maxy = abc(x, y)
--
Robert Kern rk***@ucsd.edu
"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
On Sat, 14 May 2005 20:38:26 +0200, Bernd Nawothnig <Be*************@t-online.de> wrote: On 2005-05-14, M.E.Farmer wrote:
(x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv) This will only create a tuple in memory that has no name to reference it by!
Maybe. But it does not seem to hurt. And I am not sure the tupel _is_ really created in that situation.
One way to get insight into what a statement does is to disassemble its code, e.g., import dis dis.dis(compile('(x,y,dotp,sumx,maxv) = abc(x,y,dotp,sumx,maxv)','','exec'))
1 0 LOAD_NAME 0 (abc)
3 LOAD_NAME 1 (x)
6 LOAD_NAME 2 (y)
9 LOAD_NAME 3 (dotp)
12 LOAD_NAME 4 (sumx)
15 LOAD_NAME 5 (maxv)
18 CALL_FUNCTION 5
21 UNPACK_SEQUENCE 5
24 STORE_NAME 1 (x)
27 STORE_NAME 2 (y)
30 STORE_NAME 3 (dotp)
33 STORE_NAME 4 (sumx)
36 STORE_NAME 5 (maxv)
39 LOAD_CONST 0 (None)
42 RETURN_VALUE
In the context of a function or module scope, those loads and stores will change
to optimized byte code ops like LOAD_FAST and STORE_FAST etc, but you can see what's
happening above. I.e., on return from the function call, the returned sequence (we know it's
a tuple in your example, but it could be some other sequence thing) is upacked and its elements
are bound to the individual names, just as individual "assignments" would do.
Regards,
Bengt Richter
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
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. def f(q,w,e,r):
.... return q,w,e,r
.... # diff names a,b,c,d= f(1,2,3,4)# explicit tuple unpacking dir()
['__builtins__', '__doc__', '__name__', 'a', 'b', 'c', 'd', 'f',
'shell'] del a,b,c,d # where is the tuple (a,b,c,d)= f(1,2,3,4)# implicit tuple unpacking !? dir()
['__builtins__', '__doc__', '__name__', 'a', 'b', 'c', 'd', 'f',
'shell'] del a,b,c,d # Where is the tuple (a,s,d,f)? There isn't one. # assign to a single name ( don't do tuple unpacking ) tup=f(1,2,3,4) dir()
['__builtins__', '__doc__', '__name__', 'f', 'shell', 'tup']
Now there is.
Steve since you are closer to expert than novice you understand the
difference.
I feel this can be confusing to newbies, maybe you disagree.
M.E.Farmer
I said exactly what I meant, the parantheses around the values creates
a tuple that you have no reference to! It also has a side effect of
binding the names inside the tuple to a value and placing them in the
local namespace. It might be the "same" but it isn't very clear. If you
want a tuple make it explicit, if you want individual names make it
explicit. def f(q,w,e,r):
.... return q,w,e,r
.... # diff names a,b,c,d= f(1,2,3,4)# explicit tuple unpacking dir()
['__builtins__', '__doc__', '__name__', 'a', 'b', 'c', 'd', 'f',
'shell'] del a,b,c,d # where is the tuple (a,b,c,d)= f(1,2,3,4)# implicit tuple unpacking !? dir()
['__builtins__', '__doc__', '__name__', 'a', 'b', 'c', 'd', 'f',
'shell'] del a,b,c,d # Where is the tuple (a,b,c,d)? There isn't one. # assign to a single name ( don't do tuple unpacking ) tup=f(1,2,3,4) dir()
['__builtins__', '__doc__', '__name__', 'f', 'shell', 'tup']
Now there is.
Steve since you are closer to expert than novice you understand the
difference.
I feel this can be confusing to newbies, maybe you disagree.
M.E.Farmer
M.E.Farmer 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 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.
It actually is the same, and I don't think implicit or explicit is the
difference you should be citing here. The parentheses are fully
optional -- they don't change the semantics at all:
py> t = (4, 5)
py> a = t
py> a is t
True
py> a = (b, c) = t
py> a is t
True
py> a = b, c = t
py> a is t
True
In all cases, "a" still gets assigned the tuple (4, 5). Whether or not
you put the parentheses around "b, c" is fully a matter of style.
I don't know the implementation enough to know whether or not a tuple is
actually created when "b" and "c" are bound to their values, but I'd be
willing to bet that whatever happens to "(b, c)" is exactly the same as
what happens to "b, c".
STeVe
Steven Bethard wrote: I don't know the implementation enough to know whether or not a tuple is actually created when "b" and "c" are bound to their values, but I'd be willing to bet that whatever happens to "(b, c)" is exactly the same as what happens to "b, c".
Some corroborating evidence:
py> def f(t):
.... (b, c) = t
....
py> def g(t):
.... b, c = t
....
py> import dis
py> dis.dis(f)
2 0 LOAD_FAST 0 (t)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (b)
9 STORE_FAST 1 (c)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
py> dis.dis(g)
2 0 LOAD_FAST 0 (t)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (b)
9 STORE_FAST 1 (c)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
They're both an UNPACK_SEQUENCE byte-code.
STeVe
On 14 May 2005 10:44:30 -0700, "M.E.Farmer" <me*****@hotmail.com> wrote:
[...] Be sure to study up on namespaces, it will ease your Python woes. Namespaces are the most fundamental part of Python that new users don't understand. Namespace mastery will take you far. Just remember there are only two scopes local and global ;)
And don't jump to conclusions when you read a line like the last above ;-)
I.e., there can be many different local and global scopes, not just one of each,
and since Python is a very dynamic language, existence of things can vary with
execution time and logic, so those scopes don't all have to exist at the same time,
or at all, nor persist until the program runs to its end. Also, ISTM "local" is probably
being stretched a little above to include nested scopes, which are a bit different
from either plain local or global in how you can access them.
I would second the advice to explore namespaces, and particularly attribute name spaces
such as are defined by classes. Attribute access and descriptors conspire to enable much
of the magic you can cook up with Python, as well as stuff that happens automatically.
In short, a whole unopened deluxe set of programming Legos is at your elbow, besides the
pieces you have encountered so far. Have fun ;-)
Regards,
Bengt Richter
On 14 May 2005 13:25:55 -0700, "M.E.Farmer" <me*****@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
>It actually is the same, and I don't think implicit or explicit is the difference you should be citing here.
Why not it is relevant and true that Python is doing an implicit
unpacking of the values in that unnamed tuple.
Quoting myself """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."""
So as you say, maybe it is is fully a matter of style and apparently I
don't like that style!
They're both an UNPACK_SEQUENCE byte-code.
I have dissed it myself ;)
My argument, if you can call it that, is that it is not clear that
Python is going to do a tuple unpacking here or not !
You had to dis it to find out and you are not a newbie.
# extra fluff from pyshell import dis dis.dis(compile('(x,y,dotp,sumx,maxv) =
abc(x,y,dotp,sumx,maxv)','','exec'))
0 SET_LINENO 0
3 SET_LINENO 1
6 LOAD_NAME 0 (abc)
9 LOAD_NAME 1 (x)
12 LOAD_NAME 2 (y)
15 LOAD_NAME 3 (dotp)
18 LOAD_NAME 4 (sumx)
21 LOAD_NAME 5 (maxv)
24 CALL_FUNCTION 5
27 UNPACK_SEQUENCE 5
30 STORE_NAME 1 (x)
33 STORE_NAME 2 (y)
36 STORE_NAME 3 (dotp)
39 STORE_NAME 4 (sumx)
42 STORE_NAME 5 (maxv)
45 LOAD_CONST 0 (None)
48 RETURN_VALUE dis.dis(compile('x,y,dotp,sumx,maxv =
abc(x,y,dotp,sumx,maxv)','','exec'))
0 SET_LINENO 0
3 SET_LINENO 1
6 LOAD_NAME 0 (abc)
9 LOAD_NAME 1 (x)
12 LOAD_NAME 2 (y)
15 LOAD_NAME 3 (dotp)
18 LOAD_NAME 4 (sumx)
21 LOAD_NAME 5 (maxv)
24 CALL_FUNCTION 5
27 UNPACK_SEQUENCE 5
30 STORE_NAME 1 (x)
33 STORE_NAME 2 (y)
36 STORE_NAME 3 (dotp)
39 STORE_NAME 4 (sumx)
42 STORE_NAME 5 (maxv)
45 LOAD_CONST 0 (None)
48 RETURN_VALUE dis.dis(compile('tup = abc(x,y,dotp,sumx,maxv)','','exec'))
0 SET_LINENO 0
3 SET_LINENO 1
6 LOAD_NAME 0 (abc)
9 LOAD_NAME 1 (x)
12 LOAD_NAME 2 (y)
15 LOAD_NAME 3 (dotp)
18 LOAD_NAME 4 (sumx)
21 LOAD_NAME 5 (maxv)
24 CALL_FUNCTION 5
27 STORE_NAME 6 (tup)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
You may notice that the act of assigning the return values to a unnamed
tuple and a name have different semantics and that was the real point.
The problem is why should this be the same:
a,b,c=(1,2,3)
(a,b,c)=(1,2,3)
Seems weird, non-intuitive that a tuple unpacking and tuple creation
have the same bytecode.
So why is this done? What is the reason, I am sure there are a few ;)
p.s. I am leaving out for a while and will read/followup later if
needed. Thank you all for your time.
M.E.Farmer
M.E.Farmer wrote: They're both an UNPACK_SEQUENCE byte-code. I have dissed it myself ;) My argument, if you can call it that, is that it is not clear that Python is going to do a tuple unpacking here or not !
Hmm... Well, I wouldn't say that. I think it's quite clear that
Python's doing a tuple unpacking. Just like it always does anytime
there's a comma on the left-hand side of an assignment statement.
Note that there's nothing that forces you to write the unpack sequence
like a tuple display. You can write it like a list display too, and
Python will treat it identically:
py> def unpack_tuple(t):
.... [x, y] = t
....
py> dis.dis(unpack_tuple)
2 0 LOAD_FAST 0 (t)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (x)
9 STORE_FAST 1 (y)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
I don't know how UNPACK_SEQUENCE is implemented, but at least on the
Python level, no tuple or list is created in the unpacking process.
Seems weird, non-intuitive that a tuple unpacking and tuple creation have the same bytecode.
Sorry, I don't understand. Why do you think this?
py> def create_tuple(x, y):
.... (x, y)
....
py> dis.dis(create_tuple)
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 BUILD_TUPLE 2
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
py> def unpack_tuple(t):
.... x, y = t
....
py> dis.dis(unpack_tuple)
2 0 LOAD_FAST 0 (t)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (x)
9 STORE_FAST 1 (y)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
To me, it looks like tuple creation uses the BUILD_TUPLE op-code, and
tuple unpacking uses the UNPACK_SEQUENCE op-code. Could you explain
what you meant by "a tuple unpacking and tuple creation have the same
bytecode"?
STeVe
I explained what i meant in previous post there was nothing more than
just a discussion I have no real problem here just more of a sore point
in style for me. I feel that parens are quite overloaded and it can be
confusing to newbies.
But if the parens are just fluff then get rid of them, it is clearer *
at least to me * ;)
There are enough things wrapped in parens nowadays it is starting to
look like lisp. BTW, UIAM it is the commas that define tuples, so the outermost
parens are really >expressionparens more than tuple syntax.
Hadn't really thought of that way but it makes sense w = 1,2,3 w.__doc__
"""tuple() -> an empty tuple
tuple(sequence) -> tuple initialized from sequence's items
If the argument is a tuple, the return value is the same object."""
Thanks for your time Bengt!
M.E.Farmer
Ok I give up you have convinced me. Of what I am not sure ;)
Anyway I have always viewed :
a,b,c= (1,2,3)
as unpacking a tuple
and :
(a,b,c) = (1,2,3)
as creation of a tuple
It was a false assumption, I have used Python for years and have never
written an unpacking as:
(a,b,c) = (1,2,3)
I have always put parens around my tuples I always thought that a tuple
was a parens with at least one comma ;)
It is just not something I have done, it seems counter to my thinking ,
till I read from Bengt it is the commas that make the tuple not the
parens.
It all makes sense now, but if they are not needed I think they that
should be avoided for clarity.
Steve thanks for your time. I always learn a little from you ;)
M.E.Farmer
"M.E.Farmer" <me*****@hotmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com... But if the parens are just fluff then get rid of them, it is clearer * at least to me * ;)
While I find unnecessary parens on the right of '=' tolerable, I agree as
to the style preference.
Terry J. Reedy
M.E.Farmer wrote: I said exactly what I meant, the parentheses around the values creates a tuple that you have no reference to!
repeating it doesn't make you right; no extra tuple is created, and the
parens are part of the syntax:
If the target is a target list enclosed in parentheses or in square
brackets: The object must be a sequence with the same number
of items as there are targets in the target list, and its items are
assigned, from left to right, to the corresponding targets. http://docs.python.org/ref/assignment.html
(originally, you had to use [] to unpack lists, and () or no parens only
worked for tuples. the ability to use an arbitrary sequence was added
in 1.5)
on the other hand, the function you're calling in this example *does*
create a tuple that you have no reference to after the assignment.
that doesn't matter, of course, since the tuple is removed by the
garbage collector immediately after it has been unpacked.
</F>
Bernd Nawothnig wrote: You're thinking you're passing the arguments as reference
That is the way Fortran handles them:
which is one of the things you really love when you link against
underdocumented Fortran programs from C. ("is that parameter
a scalar or an array? crash! oh, an array. how many values does
it expect? crash! oh, a few more, I suppose").
</F>
On 2005-05-14, M.E.Farmer wrote: I explained what i meant in previous post there was nothing more than just a discussion
No. You claimed
<quote>
This will only create a tuple in memory
</quote>
But we just learned that this is not the case.
I have no real problem here just more of a sore point in style for me. I feel that parens are quite overloaded and it can be confusing to newbies. But if the parens are just fluff then get rid of them, it is clearer * at least to me * ;)
Reduced to this argument I have no objection.
There are enough things wrapped in parens nowadays it is starting to look like lisp.
Lisp is far from being ugly ;-)
Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
On Sun, 15 May 2005 08:00:47 +0200, "Fredrik Lundh" <fr*****@pythonware.com> wrote: M.E.Farmer wrote:
I said exactly what I meant, the parentheses around the values creates a tuple that you have no reference to! repeating it doesn't make you right; no extra tuple is created, and the parens are part of the syntax:
If the target is a target list enclosed in parentheses or in square brackets: The object must be a sequence with the same number of items as there are targets in the target list, and its items are assigned, from left to right, to the corresponding targets.
http://docs.python.org/ref/assignment.html
(originally, you had to use [] to unpack lists, and () or no parens only worked for tuples. the ability to use an arbitrary sequence was added in 1.5)
Note that (x) without a comma doesn't unpack like [x] however: (x)= 123, x
(123,) [x]= 123, x
123 (x,)= 123, x
123 x,= 123, x
123
Also, BTW,
123,
(123,) [123,]
[123]
I.e., that last result is not [(123,)]
There's actually a bunch of context-sensitive things about commas that
you just have to get used to, in lists, tuples, function call arg lists,
subscripts (__getitem__ args), unpacking assignment targets, etc.
on the other hand, the function you're calling in this example *does* create a tuple that you have no reference to after the assignment.
Yeah, but it would create that tuple whether there was an assignment
of the returned result or not. Collecting unconnected facts in one
breath remind me too much of political speeches ;-)that doesn't matter, of course, since the tuple is removed by the garbage collector immediately after it has been unpacked.
I'm too tired to figure a humorous segue ;-)
Regards,
Bengt Richter
Fredrik Lundh wrote: which is one of the things you really love when you link against underdocumented Fortran programs from C. ("is that parameter a scalar or an array? crash! oh, an array. how many values does it expect? crash! oh, a few more, I suppose").
+1 QOTW
STeVe No. You claimed
<quote>
This will only create a tuple in memory
</quote>
That is not what I said please do not edit my words and call it a
quote!
But we just learned that this is not the case.
Yes it seems I was proven wrong and have learned much from the
discussion ;)
That is why I am here to learn from others and help if I can (
sometimes I am just plain wrong and I get the help )
Reduced to this argument I have no objection.
Glad to hear it.
Lisp is far from being ugly ;-)
Your words not mine.I never said it was ugly.
Lisp is beautiful but Python isn't Lisp, and the () *are* getting
overloaded.
M.E.Farmer
Fredrik and Bengt:
Thank you for the time.
I will study the docs and play with the shell till this is firm.
M.E.Farmer
On 2005-05-15, M.E.Farmer wrote: No. You claimed <quote> This will only create a tuple in memory </quote> That is not what I said please do not edit my words and call it a quote!
Again the whole sentence:
Message-ID: <11*********************@g14g2000cwa.googlegroups. com>
| This will only create a tuple in memory that has no name to reference
| it by!
Please check it out. I did only cut the sentence. But that did not
change the sense of the part I quoted. (As I understood it, correct me
if I'm wrong, I'm not a native English speaker). But we just learned that this is not the case. Yes it seems I was proven wrong and have learned much from the discussion ;) That is why I am here to learn from others and help if I can ( sometimes I am just plain wrong and I get the help )
I know that very well. I often learned much from such discussions too. Reduced to this argument I have no objection. Glad to hear it.
Lisp is far from being ugly ;-)
Your words not mine.I never said it was ugly. Lisp is beautiful but Python isn't Lisp, and the () *are* getting overloaded.
Understood and accepted.
Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
It looks like the docs could use some examples of the various
assignments it refers to.
I think something like Bengt posted would be a nice addition if it
included assignments with slices and dicts too.
Just a thought.
M.E.Farmer This discussion thread is closed Replies have been disabled for this discussion. Similar topics
14 posts
views
Thread by 2mc |
last post: by
|
16 posts
views
Thread by Kenneth McDonald |
last post: by
|
reply
views
Thread by bwaha |
last post: by
|
2 posts
views
Thread by Harry |
last post: by
|
4 posts
views
Thread by Hoop |
last post: by
|
1 post
views
Thread by Scheol Service |
last post: by
|
reply
views
Thread by Stodge |
last post: by
|
1 post
views
Thread by Thomas Troeger |
last post: by
|
2 posts
views
Thread by |
last post: by
| | | | | | | | | | |