new string function suggestion

Andrew Dalke dalke at
Mon Jun 13 09:49:44 CEST 2005

Andy wrote:
> What do people think of this?
> 'prefixed string'.lchop('prefix') == 'ed string'
> 'string with suffix'.rchop('suffix') == 'string with '
> 'prefix and suffix.chop('prefix', 'suffix') == ' and '

Your use case is

> I get tired of writing stuff like:
> if path.startswith('html/'):
>   path = path[len('html/'):]
> elif s.startswith('text/'):
>   path = path[len('text/'):]
> It just gets tedious, and there is duplication.  Instead I could just write:
> try:
>   path = path.lchop('html/')
>   path = path.lchop('text/')
> except SomeException:
>   pass

But your posted code doesn't implement your use case.  Consider
if path == "html/text/something".  Then the if/elif code sets
path to "text/something" while the lchop code sets it to "something".

One thing to consider is a function (or string method) which
is designed around the 'or' function, like this.  (Named 'lchop2'
but it doesn't give the same interface as your code.)

def lchop2(s, prefix):
  if s.startswith(prefix):
    return s[len(prefix):]
  return None

path = lchop2(path, "html/") or lchop2(path, "text/") or path

If I saw a function named "lchop" (or perhaps named "lchomp") I
would expect it to be (named 'lchomp3' so I can distinguish
between it and the other two)

def lchop3(s, prefix):
  if s.startswith(prefix):
    return s[len(prefix):]
  return s

and not raise an exception if the prefix/suffix doesn't match.
Though in this case your use case is not made any simpler.
Indeed it's uglier with either

newpath = path.lchop3("html/")
if newpath == path
  newpath = path.lchop3("text/")
  if newpath == path:


if path.startswith("html/"):
  path = path.lstrip("html/")
elif path.startswith("text/"):
  path = path.lstrip("text/")

I tried finding an example in the stdlib of code that would be
improved with your proposal.  Here's something that would not
be improved, from (it was the first grep hit I
looked at)

        if prefix and line[:len(prefix)] == prefix:
            line = line[len(prefix):]
            pref = prefix
            pref = ''

In your version it would be:

        if prefix:
                line = line.rstrip(prefix)
            except TheException:
                pref = ''
                pref = prefix
            pref = ''

which is longer than the original.

 From (grepping for 'endswith(' and a context of 2)    if ashex.endswith('L'):        ashex = ashex[2:-1]    else:        ashex = ashex[2:]

this would be better with my '3' variant, as

  ashex = ashex.rchop3('L')[2:]

while your version would have to be

    ashex = ashex.rchomp('L')[2:]
  except SomeException:
    ashex = ashex[2:]

Even with my '2' version it's the simpler

  ashex = (ashex.rchop2('L') or ashex)[2:]

The most common case will be for something like this        if".gz"):   =[:-3]

My "3" code handles it best =".gz")

Because your code throws an exception for what isn't
really an exceptional case it in essence needlessly
requires try/except/else logic instead of the simpler
if/elif logic.

> Does anyone else find this to be a common need?  Has this been suggested 
> before?

To summarize:
  - I don't think it's needed that often
  - I don't think your implementation's behavior (using an
       exception) is what people would expect
  - I don't think it does what you expect

				dalke at

More information about the Python-list mailing list