one to many (passing variables)
Steven D'Aprano
steve+gmane at pearwood.info
Fri Jul 25 23:43:20 EDT 2014
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
More information about the Python-list
mailing list