[Tutor] Re: streamlining a return statement
Michael Chermside
mcherm@destiny.com
Mon, 09 Sep 2002 12:49:17 -0400
Erik Price wrote:
> I have a function in a chunk of code...
>
> It works fine. But I'm wondering whether returning an empty tuple is a
> good idea...
>
> Can someone criticize my code please?
Sure. But it's just my opinion... don't be afraid to trust your own
instincts too: they seem pretty good.
> Specifically the "return"
> statements -- the first part of the function is just the way I want it.
> Also, using "if matchobj" works but is that the preferred way to detect
> whether a re.search() was successful?
Yes, it is.
> (Testing for successful
> assignment, "if matchobj = re.search()", which I admit is a Perlish way
> of looking at it, doesn't work.)
>
> def atts_detect(line):
> """searches a line for a tag with attributes and
> returns a tuple of info about the tag if attributes are found"""
>
> import re
>
> # this regex ensures that the tag the kind we want
> needle = r'(\s*)<(\w+)(\s+[-\w]+=[\'"].+[\'"])+(\s*/?>)'
> regex = re.compile(needle)
>
> # a match object is only returned if search is successful
> matchobj = regex.search(line)
> if matchobj: return matchobj.groups()
> # return an empty tuple if no matches found
> else: return ()
I can see two approaches here, both of which are pretty good style. The
first approach would be to use your code as is... making two changes.
The first (and perhaps this is already how you do it) would be to use
the truth value of the tuple returned as the indicator of whether a tag
was found or not. So I mean something like this:
def outer_program(line):
atts = atts_detect(line):
if atts:
handle_a_tag( atts[0], atts[1], atts[2] )
else:
handle_no_tag()
The other approach would be, as you suggest, to use an exception:
def outer_program(line):
try:
atts = atts_detect(line)
handle_a_tag( atts[0], atts[1], atts[2] )
except NoTagFoundException:
handle_no_tag()
It's probably fairly easy to get a big debate going about the advantages
of each, but I think the best answer has to do with how you think about
the results. If there is supposed to be a tag on each line, and a
missing tag indicates that the file is corrupt, then the exception
approach definitely makes more sense. If you expect no tag found to be
fairly common, then some people would say "never use an exception to
handle a non-error condition". (I am not one of them -- the overhead of
exceptions is larger than most normal statements, but not overwhelming
in Python, even "for" loops use exceptions for termination.)
But in EITHER case, there's one thing missing. Your docstring should
specify what happens in the unusual case. Go with one of these:
"""Searches a line for a tag with attributes. Returns a 4-element
tuple (<whitespace preceeding tag>, <tagname>, <tag attributes>,
<closing bracket>) if found, and an empty tuple if not found."""
"""Finds the first tag with attributes on the line. Returns a
4-element tuple (<whitespace preceeding tag>, <tagname>, <tag
attributes>, <closing bracket>). If no tag with attributes is
found, it raises NoTagFoundException."""
Notice that my documentation of the tuple that is returned matches what
is implemented in the code, but does NOT match your description. Was
that a bug?
-- Michael Chermside