return an object of a different class

Jean-Michel Pichavant 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 
> this:
>
> # 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 
> offset.
>
> 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.

JM



More information about the Python-list mailing list