[Python-3000] Droping find/rfind?

Nick Coghlan ncoghlan at gmail.com
Fri Aug 25 14:33:46 CEST 2006


Fredrik Lundh wrote:
> Nick Coghlan wrote:
> 
>>> Nick Coghlan wrote:
>>>
>>>> With a variety of "view types", that work like the corresponding builtin type,
>>>> but reference the original data structure instead of creating copies
>>> support for string views would require some serious interpreter surgery, though,
>>> and probably break quite a few extensions...
>> Why do you say that?
> 
> because I happen to know a lot about how Python's string types are
> implemented ?

I believe you're thinking about something far more sophisticated than what I'm 
suggesting. I'm just talking about a Python data type in a standard library 
module that trades off slower performance with smaller strings (due to extra 
method call overhead) against improved scalability (due to avoidance of 
copying strings around).

>> make a view of it
> 
> so to make a view of a string, you make a view of it ?

Yep - by using all those "start" and "stop" optional arguments to builtin 
string methods to implement the methods of a string view in pure Python. By 
creating the string view all you would really be doing is a partial 
application of start and stop arguments on all of the relevant string methods.

I've included an example below that just supports __len__, __str__ and 
partition(). The source object survives for as long as the view does - the 
idea is that the view should only last while you manipulate the string, with 
only real strings released outside the function via return statements or yield 
expressions.

All that said, I think David Hopwood nailed the simplest answer to Walter's 
particular use case with:

def splitindex(s):
     pos = 0
     while True:
       try:
           posstart = s.index("{", pos)
           posarg = s.index(" ", posstart)
           posend = s.index("}", posarg)
       except ValueError:
           break
       prefix = s[pos:posstart]
       if prefix:
           yield (None, prefix)
       yield (s[posstart+1:posarg], s[posarg+1:posend])
       pos = posend+1
     rest = s[pos:]
     if rest:
         yield (None, rest)

 >>> list(splitindex('foo{spam eggs}bar{foo bar}'))
[(None, 'foo'), ('spam', 'eggs'), (None, 'bar'), ('foo', 'bar')]

Cheers,
Nick.

# Simple string view example
class strview(object):
     def __new__(cls, source, start=None, stop=None):
         self = object.__new__(cls)
         self.source = "%s" % source
         self.start = start if start is not None else 0
         self.stop = stop if stop is not None else len(source)
         return self
     def __str__(self):
         return self.source[self.start:self.stop]
     def __len__(self):
         return self.stop - self.start
     def partition(self, sep):
         _src = self.source
         try:
             startsep = _src.index(sep, self.start, self.stop)
         except ValueError:
             # Separator wasn't found!
             return self, _NULL_STR, _NULL_STR
         # Return new views of the three string parts
         endsep = startsep + len(sep)
         return (strview(_src, self.start, startsep),
                 strview(_src, startsep, endsep),
                 strview(_src, endsep, self.stop))

_NULL_STR = strview('')

def splitview(s):
      rest = strview(s)
      while 1:
          prefix, found, rest = rest.partition("{")
          if prefix:
              yield (None, str(prefix))
          if not found:
              break
          first, found, rest = rest.partition(" ")
          if not found:
              break
          second, found, rest = rest.partition("}")
          if not found:
              break
          yield (str(first), str(second))

 >>> list(splitview('foo{spam eggs}bar{foo bar}'))
[(None, 'foo'), ('spam', 'eggs'), (None, 'bar'), ('foo', 'bar')]


-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-3000 mailing list