Returning different types based on input parameters

George Sakkis george.sakkis at gmail.com
Tue Apr 7 07:43:54 CEST 2009


On Apr 6, 7:57 pm, "andrew cooke" <and... at acooke.org> wrote:
> andrew cooke wrote:
> > George Sakkis wrote:
> >> That's more of a general API design question but I'd like to get an
> >> idea if and how things are different in Python context. AFAIK it's
> >> generally considered bad form (or worse) for functions/methods to
> >> return values of different "type" depending on the number, type and/or
> >> values of the passed parameters. I'm using "type" loosely in a duck-
> >> typing sense, not necessarily as a concrete class and its descendants,
> >> although I'm not sure if even duck-typing is endorsed for return
> >> values (as opposed to input parameters).
> > [...]
>
> > you probably want to look up substitutability:
> >http://www.google.cl/search?q=substitutability+principle
>
> actually, this is better:http://www.google.cl/search?q=substitution+principle
>
> the idea being that if the "contract" for your function is that it returns
> a certain type, then any subclass should also be ok (alternatively, that
> subclasses should be written so that they can be returned when a caller
> was expecting the superclass)

I'm not sure if Liskov substitution addresses the same problem. The
question here is, what's the scope of the contract ? Does it apply to
the original signature only or any future extended version of it ? In
the former case, the contract is still valid: whenever someone calls
"solve(x)" gets the promised type. The original contract didn't
specify what should the result be when the function is called as "solve
(x, y)" (since the function didn't support a second argument
originally). Only if one interprets the contract as applicable to the
current plus all future extensions, then Liskov substitution comes
into play.

Perhaps that's more obvious in statically typed languages that allow
overloading. IIRC the presence of a method with the signature
   float foo(float x);
does not preclude its overloading (in the same or a descendant class)
with a method
   char* foo(float x, int y);
The two methods just happen to share the same name but other than that
they are separate, their return value doesn't have to be
substitutable. Is this considered bad practice ?

George



More information about the Python-list mailing list