On Fri, 25 Jul 2014 18:47:55 -0700, C.D. Reimer wrote: > On 7/24/2014 2:58 AM, Ben Finney wrote: >> Here is an article on good API design; the principles apply to Python >> <URL:http://blog.isnotworking.com/2007/05/api-design-guidelines.html>. >> You know your API and its requirements better than we; see whether that >> sheds any light on improvements to make. > Thank you for the link. I'm curious about one item mentioned in the > article: "Avoid return values that Demand Exceptional Processing: return > zero-length array or empty collection, not null" > > Isn't a zero-length array, empty collection and null all the same thing?
No. Since an array is a kind of collection, a zero-length array is an empty array, which is an empty collection. But null is not the same thing. In Python terms, it is the difference between: return [] return None While I agree that in general it is better to return (say) a consistent list result, sometimes you need an exceptional result that is different from the "empty" or "zero" result. In that case, there are two obvious ways to deal with exceptional circumstances: - raise an exception, e.g. "spam".index("e") raises - return a special result, e.g. "spam".find("e") returns -1 Raising an exception is the obvious way to handle it, but exception handling is a little less convenient than testing for a special value. Hence the find() convenience method. However, find() makes a silly mistake: it returns -1 to indicate Not Found, and -1 is acceptable as an index. So if you forget to test for the Not Found case, you might write this: p = some_string.find(needle) return another_string[p] which is wrong. If find() returns -1, another_string[p] returns the *last* character in the string, which is probably not what you want. A better API is that of the regular expression module. re.search() and re.match() return either a match object, or None if the regex doesn't match at all. So if you forget to test for None, and blindly try to treat the result as if it where a match object, you will immediately get an exception instead of invalid results: mo = re.search(text, needle) return mo.group() # will raise if mo is None In summary: * if you're returning a list of results, deal with no results by returning an empty list [] rather than None; * if you need to distinguish between the empty list case and some exceptional situation, the best way is to raise an exception; * if you don't wish to raise an exception, it is better to return some result which clearly cannot be mistaken for, or accidentally used as, a regular non-exceptional result; * e.g. if your function normally returns an integer, better to return None as a "no result exists" than 0 or -1, since they are valid integers and None isn't. -- Steven -- https://mail.python.org/mailman/listinfo/python-list