Python function returns:

  • Thread starter Michael Yanowitz
  • Start date
M

Michael Yanowitz

I am still new to Python but have used it for the last 2+ months.
One thing I'm still not used to is that functions parameters can't
change as expected. For example in C, I can have
status = get_network_info (strIpAddress, &strHostname, &nPortNumber)
where this fictitious function returns a status, but also returns modified
values for a hostname and a port number.
In Python, there does not seem to be an easy way to have functions return
multiple values except it can return a list such as:
strHostname, nPortNumber, status = get_network_info (strIpAddress,
strHostname,
nPortNumber)
Am I missing something obvious? Is there a better, or more standard way
to return values from functions?

Thanks in advance:
Michael Yanowitz
 
D

Diez B. Roggisch

Michael said:
I am still new to Python but have used it for the last 2+ months.
One thing I'm still not used to is that functions parameters can't
change as expected. For example in C, I can have
status = get_network_info (strIpAddress, &strHostname, &nPortNumber)
where this fictitious function returns a status, but also returns
modified
values for a hostname and a port number.
In Python, there does not seem to be an easy way to have functions
return
multiple values except it can return a list such as:
strHostname, nPortNumber, status = get_network_info (strIpAddress,
strHostname,
nPortNumber)
Am I missing something obvious? Is there a better, or more standard way
to return values from functions?

No, that exactly is the way to go. But usually one uses tuples and the
possibility of sequence-unpacking together to reach a solution tha at least
to my eye looks more favorable:


def foo(a, b):
return a*b, a+c

a = 10
b = 20

a, b = foo(a, b)


Diez
 
D

Duncan Booth

Michael said:
In Python, there does not seem to be an easy way to have functions
return
multiple values except it can return a list such as:
strHostname, nPortNumber, status = get_network_info (strIpAddress,
strHostname,
nPortNumber)
Am I missing something obvious? Is there a better, or more standard
way
to return values from functions?

The only obvious thing you are missing is that you don't pass in values
which are only results. Duplicating the parameters and results as you have
above would be unlikely to happen very much in practice.

Oh, and it doesn't return a list, it actually returns a tuple but it is
easiest just to think of your function as just returning three results.

Returning additional results is better than rebinding parameters because it
makes it really clear at the point of calling which variables are
parameters and which are results.

The other not very pythonic thing about your example is that it returns a
status code: Python largely tends towards using exceptions rather than
status codes, so if in C you had:

switch ((status=get_network_info(addr, &host, &port)) {
case S_OK:
break;
case ERROR_1:
... handle error ...
break;
case default:
... handle other errors ...
};

In Python you would have something like:

try:
host, port = get_network_info(addr)
except ERROR_1:
... handle error ...
except:
... handle other errors ...

which means you can handle the error either right next to the call or at
some outer level (you don't have to manually propogate your status), you
can't accidentally forget to check the status code, and the actual call is
much simpler and clearer (especially if the error is handled at some outer
level).
 
B

bruno at modulix

Michael said:
I am still new to Python but have used it for the last 2+ months.
One thing I'm still not used to is that functions parameters can't
change as expected.

For example in C, I can have
status = get_network_info (strIpAddress, &strHostname, &nPortNumber)

You have to understand that Python and C are totally different beasts.

A C variable is mostly symbolic name for a memory address, tagged with
type infos. Assigning to a variable means storing a value at this
address. Reading a variable means retrieving whatever value is stored at
this memory address.

Python does not in fact have a concept of "variables". It has names and
objects. A binding is the association (in a hash table) of a symbolic
name (which is nothing more than a name) and a reference (read:
something like a smart pointer) to an object (which is itself a complex
data structure). So-called "assignement" (correct term is "binding")
'binds' together a name and a reference to an object. Except for some
special cases (mainly objects - which are they're own namespaces - and
when using the 'global' statement), this creates an entry in the current
namespace. Also, rebinding a name has no effect on other names bound to
the same object.

Function's params are bindings in the function's local namespace. This
means that the params *names* are local to the function. So rebinding a
param in a function won't have no effect on bindings in the caller's
namespace.

*But* - since many names can refer to the same object - *modifying* the
object referenced by a name will, well, modify this object, so this
modification will be visible everywhere.

ie (dummy example):

def appendToList(alist, what):
alist.append(what)

mylist = []
appendToList(mylist, 42)
print mylist

What doesn't work as you'd expect is:

def failsToHaveSideEffects(alist, anything):
print "before rebinding : alist = ", alist, " - anything = ", anything
alist = anything
print "after rebinding: alist = ", alist

mylist = []
print "before function call, mylist = ", mylist
failsToHaveSideEffects(mylist, 42)
print "after function call, mylist = ", mylist


So as you can see, it's quite possible for a function to *modify* it's
params - it's just rebindings of params that won't have side effects
outside the function's namespace.

Now, there is the case of immutable types (int, strings, tuples, ....).
As implied, one cannot modify objects of these types - just create them.
So in order to have a function that "change the value" of an immutable
object, you have to wrap it into a mutable object, ie:

def getAnswer(alist):
alist[0] = "42"

answer = ["answer is ?"]
getAnswer(answer)
print "answer is : ", answer[0]

(snip)
In Python, there does not seem to be an easy way to have functions return
multiple values except it can return a list such as:
strHostname, nPortNumber, status = get_network_info (strIpAddress,
strHostname,
nPortNumber)
Am I missing something obvious? Is there a better, or more standard way
to return values from functions?

This *is* the 'standard' (ie: idiomatic) way to return multiple values
from a function. The C idiom of passing pointers to variables that are
to be modified comes from C's limitations, namely no exception handling
and only one return value[1], which leads to using the return value as a
status report and relying on side effect for useful values.



[1] To be pedantic, Python only allows one return value too - but this
value can be a tuple or list, and then one can take advantage of
tuple/list expansions that allows multiple assignment...

HTH
 
S

Sion Arrowsmith

Michael Yanowitz said:
In Python, there does not seem to be an easy way to have functions return
multiple values except it can return a list such as:
strHostname, nPortNumber, status = get_network_info (strIpAddress,
strHostname,
nPortNumber)
Am I missing something obvious? Is there a better, or more standard way
to return values from functions?

I'm kind of repeating what other people have said, but there
isn't a better way. Not just in Python, but in any language.
If your function is returning multiple values, why should you
have to split them into one privileged "return value" plus a
bunch of Out (or InOut) parameters? That's a historical mis-
feature of older languages, and one which more newer languages
would do well to fix.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,206
Latest member
EpifaniaMc

Latest Threads

Top