On Fri, 26 Jan 2007 18:28:32 +0000, Matthew Woodcraft wrote: > I have a question for you. Consider this function: > > def f(n): > """Return the largest natural power of 2 which does not exceed n.""" > if n < 1: > raise ValueError > i = 1 > while i <= n: > j = i > i *= 2 > return j > > If I pass it an instance of MyNumericClass, it will return an int or a > long, not an instance of MyNumericClass. > > In your view, is this a weakness of the implementation? Should the > author of the function make an effort to have it return a value of the > same type that it was passed?
Only if it makes sense in the context of the function. I'd say it depends on the principle of "least surprise": if the caller would expect that passing in a MyNumericClass or a float or a Rational should return the same type, then Yes, otherwise its optional. Numeric functions are probably the least convincing example of this, because in general people expect numeric functions to coerce arguments in not-always-intuitive ways, especially when they pass multiple arguments of mixed types. What should g(MyNumericClass, int, float, Rational) return? And it often doesn't matter, not if you're just doing arithmetic, because (in principle) any numeric type is compatible with any other numeric type. The principle of least surprise is sometimes hard to follow because it means putting yourself in the shoes of random callers. Who knows what they expect? One rule of thumb I use is to consider the function I'm writing, and its relationship to the argument. Would I consider that the result is somehow _made_from_ the argument? If so, then I should return the same type (unless there is a compelling reason not to). I'm NOT talking about implementation here, I'm thinking abstract functions. Whether your implementation actually transforms the initial argument, or creates a new piece of data from scratch, is irrelevant. In your above example, the result isn't "made from" the argument (although some implementations, using log, might do so). In abstract, the result is an integer that is chosen by comparison to the argument, not by construction from the argument. So it is unimportant for it to be the same type, and in fact the caller might expect that the result is an int no matter what argument he passes. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list