re Challenge: More Compact?

Tim Hammerquist tim at vegeta.ath.cx
Mon Jul 16 04:39:50 CEST 2001


Me parece que Tim Peters <tim.one at home.com> dijo:
> [Tim Hammerquist]
> > ...
> > Easily implemented in Perl:
> >
> >: sub valid_ip {
> >:     my ($ip, $failed, @elements) = (shift, 0);
> >:     @elements = ($ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
> >:     $failed = grep { $_ > 255 } @elements;
> >:     return ($failed) ? undef : 1;
> >: }
> >
> > Slightly more verbose in Python:
> >
> >: import re
> >: def valid_ip(ip):
> >:     expr = r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$'
> >:     elements = map(int, re.match(expr, ip).groups())
> >:     failed = filter(lambda x: x > 255, elements)
> >:     if failed:  return None
> >:     else:       return 1
> 
> Well, it's un-Pythonic to try to emulate Perl undef via Python None; it's
> idiomatic to return 0 for false and 1 for true, in which case the last three
> lines can be replaced by, e.g.,
> 
>     return max(elements) < 256

Fair enough.  I'm in the habit (in Python as well) of return undef on
false because in some methods, 0 is ambiguous.  So, in cases where 0 is
not ambiguous, 0 is idiomatically preferred to None?

> Note that the leading "^" in the Python regexp isn't needed (can save
> another entire character that way <wink>).

Oh yeah.  re.match() starts at the beginning.

> The Python version should also check for match failure.  Like
> 
> def valid_ip(ip):
>     m = re.match(r'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', ip)
>     if m:
>         elements = map(int, m.groups())
>         return max(elements) < 256
>     return 0
> 
> Yes, you can squash lines out of that -- I wouldn't.

I see I need practice in Python idioms (tho my Perl version didn't do
a whole lot of error checking either).  All I'd do is move the map()
call inside the max() call.

Ok, so here's my version (I hate wasted line space and unnecessary temp
vars):

def valid_ip(ip):
    m = re.match( r'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', ip)
    if m:   return max(map(int, m.groups())) < 256
    return 0

> BTW, does it bother anyone that all of these solutions accept an IP ending
> with a newline?

Just add '(?!\n)' right before the '$'.  <wink>

> regexps-are-surprising-ly y'rs  - tim

-- 
I am following my fish.
    -- Delirium, The Sandman



More information about the Python-list mailing list