Reputation: 4644
This question was already asked, but I wish to ask something subtly different.
How do we determine if a python function returns multiple values, without calling the function? Is there some way to find out at something more like compile-time instead of at run-time? (I realize that python is an interpreted language)
The following is out of the question:
r = demo_function(data) # takes more than 5 minutes to run
if (not len(r) == 2) or (not isinstance(r, tuple)):
raise ValueError("I was supposed to return EXACTLY two things")
So is:
try:
i, j = demo_function(data)
# I throw TypeError: 'int' object is not iterable
except ValueError:
raise ValueError("Hey! I was expecting two values.")
except TypeError:
s1 = "Hey! I was expecting two values."
s2 = "Also, TypeError was thrown, not ValueError"
raise ValueError(s1 + s2)
The following sort of works, but is extremely inelegant:
r = demo_function(extremely_pruned_down_toy_data) # runs fast
if len(r) != 2:
raise ValueError("There are supposed to be two outputs")
# Now we run it for real
r = demo_function(data) # takes more than 5 minutes to run
There are tools already in python which do similar things. For example, we can find out if a class object has a certain attribute:
prop_str = 'property'
if not hasattr(obj, prop_str):
raise ValueError("There is no attribute named" + prop_str + " NOOOOoooo! ")
Also, we can find out how many INPUTS a function has:
from inspect import signature
sig = signature(demo_function)
p = sig.parameters
if len(p)) != 2:
raise ValueError("The function is supposed to have 2 inputs, but it has" + str(p))
I basically want the following:
p = nargout(demo_function)
if p != 2:
raise ValueError("The function is supposed to have 2 outputs, but it has" + str(p))
Asking what a function returns is one of the most basic things questions one can ask about a function. It feels really weird that I'm having trouble finding out.
juanpa.arrivillaga wrote,
[...] fundamentally, this points to a deeper, underlying design flaw: why do you have functions that can return different length containers when you are expecting a specific length?
Well, let me explain. I have something like this:
def process_data(data_processor, data):
x, y = data_processor(data)
return x, y
A precondition of the process_data
function is that the input data_processor
MUST return two items. As such, I want to write some error checking code to enforce the precondition.
def process_data(data_processor, data):
# make sure data_processor returns exactly two things!
verify_data_processor(data_processor)
x, y = data_processor(data)
return x, y
However, it looks like that's not easily doable.
Upvotes: 4
Views: 101
Reputation: 95873
A function really only has a single return value. It can return a container, such as a tuple
, of whatever length. But there is no inherent way for a Python function to know the length of such a value, Python is much too dynamic. Indeed, in general, the interpreter does not know the nature of the return value of a function. But even if we stick to just considering functions that return containers, consider the following function:
def howmany(n):
return n*('foo',)
Well, what should nargout(howmany)
return?
And python does not special case something like return x, y
, nor should it, because then what should be the behavior when the length of the returned container is indeterminate, such as return n*(1,)
? No, it is up to the caller to deal with the case of a function returning a container, in one of the ways you've already illustrated.
And fundamentally, this points to a deeper, underlying design flaw: why do you have functions that can return different length containers when you are expecting a specific length?
Upvotes: 5