Returning different types based on input parameters

Adam Olsen rhamph at gmail.com
Tue Apr 7 15:18:26 EDT 2009


On Apr 6, 3:02 pm, George Sakkis <george.sak... at gmail.com> wrote:
> For example, it is common for a function f(x) to expect x to be simply
> iterable, without caring of its exact type. Is it ok though for f to
> return a list for some types/values of x, a tuple for others and a
> generator for everything else (assuming it's documented), or it should
> always return the most general (iterator in this example) ?

For list/tuple/iterable the correlation with the argument's type is
purely superficial, *because* they're so compatible.  Why should only
tuples and lists get special behaviour?  Why shouldn't every other
argument type return a list as well?

A counter example is python 3.0's str/bytes functions.  They're
mutually incompatible and there's no default.


> To take it further, what if f wants to return different types,
> differing even in a duck-type sense? That's easier to illustrate in a
> API-extension scenario. Say that there is an existing function `solve
> (x)` that returns `Result` instances.  Later someone wants to extend f
> by allowing an extra optional parameter `foo`, making the signature
> `solve(x, foo=None)`. As long as the return value remains backward
> compatible, everything's fine. However, what if in the extended case,
> solve() has to return some *additional* information apart from
> `Result`, say the confidence that the result is correct ? In short,
> the extended API would be:
>
>     def solve(x, foo=None):
>         '''
>         @rtype: `Result` if foo is None; (`Result`, confidence)
> otherwise.
>         '''
>
> Strictly speaking, the extension is backwards compatible; previous
> code that used `solve(x)` will still get back `Result`s. The problem
> is that in new code you can't tell what `solve(x,y)` returns unless
> you know something about `y`. My question is, is this totally
> unacceptable and should better be replaced by a new function `solve2
> (x, foo=None)` that always returns (`Result`, confidence) tuples, or
> it might be a justifiable cost ? Any other API extension approaches
> that are applicable to such situations ?

At a minimum it's highly undesirable.  You lose a lot of readability/
maintainability.  solve2/solve_ex is a little ugly, but that's less
overall, so it's the better option.

If your tuple gets to 3 or more I'd start wondering if you should
return a single instance, with the return values as attributes.  If
Result is already such a thing I'd look even with a tuple of 2 to see
if that's appropriate.



More information about the Python-list mailing list