return an object of a different class
jeanmichel at sequans.com
Tue Feb 22 13:43:19 CET 2011
Steven D'Aprano wrote:
> On Mon, 21 Feb 2011 14:23:10 +0100, Jean-Michel Pichavant wrote:
>> What is not legit, is to return different objects for which the caller
>> has to test the type to know what attributes he can use.
> Well, I don't know... I'm of two minds.
> On the one hand, I find it *really annoying* when this happens:
>>>> re.search(pattern, text).group()
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> AttributeError: 'NoneType' object has no attribute 'group'
> The problem is that re.search and re.match return None instead of a match-
> object when they don't find anything. Perhaps they should return an empty
> match object?
> But on the other hand, there is a well known failure mode caused by doing
> # Strip everything after a comment symbol.
> offset = text.find("#")
> text = text[:offset]
> See the bug? If there's no # in the string, it drops the last character.
> The most insidious part of the bug is that you might not notice, if your
> strings end with whitespace. If str.find() returned None, at least you
> would get a nice TypeError as soon as you tried to use it as a integer
> So, it's not clear to me whether under *these* circumstances it's better
> to return a completely different type, which cannot possibly be mistaken
> for success, or a magic value of the same type.
> (The third alternative is to raise an exception, and the unspeakably
> awful alternative is to have a single global error flag for the operation
> which must be checked.)
A rule cannot be 100% effective in any situation. At least that's the
case of this one. First of all, I think the rule is incomplete as I
stated it, None is an acceptable inconsistent type and can be returned
in some cases (if documented). Thanks to how logical operators work, you
can sometimes nicely handle 'None' values:
myMatch = re.search(pattern, text)
print (myMatch and myMatch.group()) or 'No text found'
Your second point with the find method illustrates another problem,
handled by a very similar rule:
"Return values must be consistent in their meaning".
This is my personal preferences but I quite dislike this type of
inconsistent meaning, find should have raised an exception or returned
the None value if nothing is found. The -1 value meaning 'not found' is
very 80's old C style coding.
More information about the Python-list