[Python-ideas] What are the strong use cases for str.rindex()?

Terry Reedy tjreedy at udel.edu
Tue Apr 23 13:52:48 EDT 2019


On 4/23/2019 2:44 AM, 林自均 wrote:
> Hi all,
> 
> I found that there are str.index() and str.rindex(), but there is only 
> list.index() and no list.rindex().

str.index and list.index are related but not the same.  The consistency 
argument is better applied to find-rfind, index-rindex, 
partition-rpartition, etc.

It is much more common to process strings right to left or in both 
directions, than process lists right to left or in both directions. 
Moreover, lists have a reverse method, strings do not.
''.join(reversed(somestring)) is likely slower, especially if there many 
non-ascii chars.  Moreover, somestring.rindex(substring) would have to 
have both somestring and substring reversed when substring is more than 
one char.

  So I filed the issue
> https://bugs.python.org/issue36639 to provide list.rindex(). However, 
> the issue was rejected and closed with the comment:
> 
>  > There were known, strong use cases for str.rindex().  The 
> list.rindex() method was intentionally omitted.  AFAICT no compelling 
> use cases have arisen, so we should continue to leave it out.  In 
> general, we don't grow the core APIs unnecessarily.
> 
> However, I am not sure what the known, strong use cases for str.rindex() 
> are. Why doesn't the strong use cases apply on list.rindex()? Could 
> anyone give me some examples? Thanks.

Omitting tests of rindex and rfind themselves:

Searching 'rindex' in C:\Programs\Python38\lib\*.py ...
C:\Programs\Python38\lib\_markupbase.py: 55:             pos = 
rawdata.rindex("\n", i, j) # Should not fail
C:\Programs\Python38\lib\collections\__init__.py: 1260:     def 
rindex(self, sub, start=0, end=_sys.maxsize):
C:\Programs\Python38\lib\collections\__init__.py: 1261:         return 
self.data.rindex(sub, start, end)
C:\Programs\Python38\lib\pydoc_data\topics.py: 10125: 
'str.rindex(sub[, start[, end]])\n'
C:\Programs\Python38\lib\test\pickletester.py: 2543: 
     self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
C:\Programs\Python38\lib\test\pickletester.py: 2574: 
     self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
C:\Programs\Python38\lib\test\test_baseexception.py: 46: 
depth = exc_line.rindex('-')
C:\Programs\Python38\lib\test\test_bigmem.py: 310: 
self.assertEqual(s.rindex(_(' ')),
C:\Programs\Python38\lib\test\test_bigmem.py: 311: 
    sublen + size + SUBSTR.rindex(_(' ')))
C:\Programs\Python38\lib\test\test_bigmem.py: 312: 
self.assertEqual(s.rindex(SUBSTR), sublen + size)
C:\Programs\Python38\lib\test\test_bigmem.py: 313: 
self.assertEqual(s.rindex(_(' '), 0, sublen + size - 1),
C:\Programs\Python38\lib\test\test_bigmem.py: 314: 
    SUBSTR.rindex(_(' ')))
C:\Programs\Python38\lib\test\test_bigmem.py: 315: 
self.assertEqual(s.rindex(SUBSTR, 0, sublen + size), 0)
C:\Programs\Python38\lib\test\test_bigmem.py: 316: 
self.assertEqual(s.rindex(_('i')),
C:\Programs\Python38\lib\test\test_bigmem.py: 317: 
    sublen + size + SUBSTR.rindex(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 318: 
self.assertEqual(s.rindex(_('i'), 0, sublen), SUBSTR.rindex(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 319: 
self.assertEqual(s.rindex(_('i'), 0, sublen + size),
C:\Programs\Python38\lib\test\test_bigmem.py: 320: 
    SUBSTR.rindex(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 321: 
self.assertRaises(ValueError, s.rindex, _('j'))
C:\Programs\Python38\lib\test\test_bytes.py: 566: 
self.assertEqual(b.rindex(b'ss'), 5)
C:\Programs\Python38\lib\test\test_bytes.py: 567: 
self.assertRaises(ValueError, b.rindex, b'w')
C:\Programs\Python38\lib\test\test_bytes.py: 568: 
self.assertRaises(ValueError, b.rindex, b'mississippian')
C:\Programs\Python38\lib\test\test_bytes.py: 570: 
self.assertEqual(b.rindex(i), 10)
C:\Programs\Python38\lib\test\test_bytes.py: 571: 
self.assertRaises(ValueError, b.rindex, w)
C:\Programs\Python38\lib\test\test_bytes.py: 573: 
self.assertEqual(b.rindex(b'ss', 3), 5)
C:\Programs\Python38\lib\test\test_bytes.py: 574: 
self.assertEqual(b.rindex(b'ss', 0, 6), 2)
C:\Programs\Python38\lib\test\test_bytes.py: 576: 
self.assertEqual(b.rindex(i, 1, 3), 1)
C:\Programs\Python38\lib\test\test_bytes.py: 577: 
self.assertEqual(b.rindex(i, 3, 9), 7)
C:\Programs\Python38\lib\test\test_bytes.py: 578: 
self.assertRaises(ValueError, b.rindex, w, 1, 3)
C:\Programs\Python38\lib\test\test_bytes.py: 768: 
self.assertEqual(3, b.rindex(l, None))
C:\Programs\Python38\lib\test\test_bytes.py: 769: 
self.assertEqual(3, b.rindex(l, -2, None))
C:\Programs\Python38\lib\test\test_bytes.py: 770: 
self.assertEqual(2, b.rindex(l, None, -2))
C:\Programs\Python38\lib\test\test_bytes.py: 771: 
self.assertEqual(0, b.rindex(h, None, None))
C:\Programs\Python38\lib\test\test_bytes.py: 791:         for method in 
(b.count, b.find, b.index, b.rfind, b.rindex):
C:\Programs\Python38\lib\test\test_bytes.py: 806: 
self.assertRaisesRegex(TypeError, r'\brindex\b', b.rindex,
C:\Programs\Python38\lib\test\test_descr.py: 3596:         try: 
''.rindex('5')
C:\Programs\Python38\lib\test\test_descr.py: 3598:         else: 
self.fail("''.rindex('5') doesn't raise ValueError")

Searching 'rfind' in C:\Programs\Python38\lib\*.py ...
C:\Programs\Python38\lib\collections\__init__.py: 1256:     def 
rfind(self, sub, start=0, end=_sys.maxsize):
C:\Programs\Python38\lib\collections\__init__.py: 1259:         return 
self.data.rfind(sub, start, end)
C:\Programs\Python38\lib\ctypes\macholib\dyld.py: 143:     fmwk_index = 
fn.rfind('.framework')
C:\Programs\Python38\lib\doctest.py: 341:     i = msg.rfind('.', 0, end)
C:\Programs\Python38\lib\email\_parseaddr.py: 76:         i = 
data[0].rfind(',')
C:\Programs\Python38\lib\encodings\punycode.py: 187:     pos = 
text.rfind(b"-")
C:\Programs\Python38\lib\formatter.py: 401:         i = data.rfind('\n')
C:\Programs\Python38\lib\genericpath.py: 124:     sepIndex = p.rfind(sep)
C:\Programs\Python38\lib\genericpath.py: 126:         altsepIndex = 
p.rfind(altsep)
C:\Programs\Python38\lib\genericpath.py: 129:     dotIndex = p.rfind(extsep)
C:\Programs\Python38\lib\html\parser.py: 148:                     amppos 
= rawdata.rfind('&', max(i, n-34))
C:\Programs\Python38\lib\html\parser.py: 336:                          - 
self.__starttag_text.rfind("\n")
C:\Programs\Python38\lib\http\client.py: 873:             i = 
host.rfind(':')
C:\Programs\Python38\lib\http\client.py: 874:             j = 
host.rfind(']')         # ipv6 addresses have [...]
C:\Programs\Python38\lib\http\cookiejar.py: 566:     i = A.rfind(B)
C:\Programs\Python38\lib\http\cookiejar.py: 1016:                 i = 
domain.rfind(".")
C:\Programs\Python38\lib\http\cookiejar.py: 1017:                 j = 
domain.rfind(".", 0, i)
C:\Programs\Python38\lib\http\cookiejar.py: 1507:             i = 
path.rfind("/")
C:\Programs\Python38\lib\idlelib\pyparse.py: 161:             i = 
code.rfind(":\n", 0, limit)
C:\Programs\Python38\lib\idlelib\pyparse.py: 164:             i = 
code.rfind('\n', 0, i) + 1  # start of colon line (-1+1=0)
C:\Programs\Python38\lib\idlelib\pyparse.py: 379:                 p = 
code.rfind('\n', 0, p-1) + 1
C:\Programs\Python38\lib\idlelib\pyparse.py: 477:         origi = i = 
code.rfind('\n', 0, j) + 1
C:\Programs\Python38\lib\json\decoder.py: 33:         colno = pos - 
doc.rfind('\n', 0, pos)
C:\Programs\Python38\lib\logging\__init__.py: 1340:         i = 
name.rfind(".")
C:\Programs\Python38\lib\logging\__init__.py: 1353:             i = 
name.rfind(".", 0, i - 1)
C:\Programs\Python38\lib\modulefinder.py: 155:             i = 
pname.rfind('.')
C:\Programs\Python38\lib\modulefinder.py: 509:             i = 
name.rfind(".")
C:\Programs\Python38\lib\pathlib.py: 791:         i = name.rfind('.')
C:\Programs\Python38\lib\pathlib.py: 810:         i = name.rfind('.')
C:\Programs\Python38\lib\pdb.py: 629:         colon = arg.rfind(':')
C:\Programs\Python38\lib\pdb.py: 884:             i = arg.rfind(':')
C:\Programs\Python38\lib\posixpath.py: 109:     i = p.rfind(sep) + 1
C:\Programs\Python38\lib\posixpath.py: 148:     i = p.rfind(sep) + 1
C:\Programs\Python38\lib\posixpath.py: 158:     i = p.rfind(sep) + 1
C:\Programs\Python38\lib\pyclbr.py: 145:     i = module.rfind('.')
C:\Programs\Python38\lib\pydoc.py: 1657:         desc += ' in ' + 
name[:name.rfind('.')]
C:\Programs\Python38\lib\pydoc_data\topics.py: 10115: 
'str.rfind(sub[, start[, end]])\n'
C:\Programs\Python38\lib\pydoc_data\topics.py: 10127: 
'   Like "rfind()" but raises "ValueError" when the '
C:\Programs\Python38\lib\site-packages\pip\_vendor\html5lib\_inputstream.py: 
228:         lastLinePos = chunk.rfind('\n', 0, offset)
C:\Programs\Python38\lib\site-packages\pip\_vendor\pyparsing.py: 1110: 
   return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - 
s.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\pip\_vendor\pyparsing.py: 1127: 
   lastCR = strg.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\pip\_vendor\pytoml\parser.py: 
169:         suffix_pos = s.rfind('\n')
C:\Programs\Python38\lib\site-packages\pkg_resources\_vendor\pyparsing.py: 
979:     return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - 
s.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\pkg_resources\_vendor\pyparsing.py: 
996:     lastCR = strg.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\setuptools\_vendor\pyparsing.py: 
979:     return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - 
s.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\setuptools\_vendor\pyparsing.py: 
996:     lastCR = strg.rfind("\n", 0, loc)
C:\Programs\Python38\lib\site-packages\setuptools\msvc.py: 627: 
        intver = ver[:ver.rfind('.')]
C:\Programs\Python38\lib\smtpd.py: 941:         lastdot = 
classname.rfind(".")
C:\Programs\Python38\lib\smtplib.py: 326:         if not port and 
(host.find(':') == host.rfind(':')):
C:\Programs\Python38\lib\smtplib.py: 327:             i = host.rfind(':')
C:\Programs\Python38\lib\sre_constants.py: 48:             self.colno = 
pos - pattern.rfind(newline, 0, pos)
C:\Programs\Python38\lib\test\test_bigmem.py: 294: 
self.assertEqual(s.rfind(_(' ')), sublen + size + SUBSTR.rfind(_(' ')))
C:\Programs\Python38\lib\test\test_bigmem.py: 295: 
self.assertEqual(s.rfind(SUBSTR), sublen + size)
C:\Programs\Python38\lib\test\test_bigmem.py: 296: 
self.assertEqual(s.rfind(_(' '), 0, size), SUBSTR.rfind(_(' ')))
C:\Programs\Python38\lib\test\test_bigmem.py: 297: 
self.assertEqual(s.rfind(SUBSTR, 0, sublen + size), 0)
C:\Programs\Python38\lib\test\test_bigmem.py: 298: 
self.assertEqual(s.rfind(_('i')), sublen + size + SUBSTR.rfind(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 299: 
self.assertEqual(s.rfind(_('i'), 0, sublen), SUBSTR.rfind(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 300: 
self.assertEqual(s.rfind(_('i'), 0, sublen + size),
C:\Programs\Python38\lib\test\test_bigmem.py: 301: 
    SUBSTR.rfind(_('i')))
C:\Programs\Python38\lib\test\test_bigmem.py: 302: 
self.assertEqual(s.rfind(_('j')), -1)
C:\Programs\Python38\lib\test\test_bytes.py: 527: 
self.assertEqual(b.rfind(b'ss'), 5)
C:\Programs\Python38\lib\test\test_bytes.py: 528: 
self.assertEqual(b.rfind(b'w'), -1)
C:\Programs\Python38\lib\test\test_bytes.py: 529: 
self.assertEqual(b.rfind(b'mississippian'), -1)
C:\Programs\Python38\lib\test\test_bytes.py: 531: 
self.assertEqual(b.rfind(i), 10)
C:\Programs\Python38\lib\test\test_bytes.py: 532: 
self.assertEqual(b.rfind(w), -1)
C:\Programs\Python38\lib\test\test_bytes.py: 534: 
self.assertEqual(b.rfind(b'ss', 3), 5)
C:\Programs\Python38\lib\test\test_bytes.py: 535: 
self.assertEqual(b.rfind(b'ss', 0, 6), 2)
C:\Programs\Python38\lib\test\test_bytes.py: 537: 
self.assertEqual(b.rfind(i, 1, 3), 1)
C:\Programs\Python38\lib\test\test_bytes.py: 538: 
self.assertEqual(b.rfind(i, 3, 9), 7)
C:\Programs\Python38\lib\test\test_bytes.py: 539: 
self.assertEqual(b.rfind(w, 1, 3), -1)
C:\Programs\Python38\lib\test\test_bytes.py: 758: 
self.assertEqual(3, b.rfind(l, None))
C:\Programs\Python38\lib\test\test_bytes.py: 759: 
self.assertEqual(3, b.rfind(l, -2, None))
C:\Programs\Python38\lib\test\test_bytes.py: 760: 
self.assertEqual(2, b.rfind(l, None, -2))
C:\Programs\Python38\lib\test\test_bytes.py: 761: 
self.assertEqual(0, b.rfind(h, None, None))
C:\Programs\Python38\lib\test\test_bytes.py: 791:         for method in 
(b.count, b.find, b.index, b.rfind, b.rindex):
C:\Programs\Python38\lib\test\test_bytes.py: 802: 
self.assertRaisesRegex(TypeError, r'\brfind\b', b.rfind,
C:\Programs\Python38\lib\test\test_mmap.py: 296: 
self.assertEqual(m.rfind(b'one'), 8)
C:\Programs\Python38\lib\test\test_mmap.py: 297: 
self.assertEqual(m.rfind(b'one '), 0)
C:\Programs\Python38\lib\test\test_mmap.py: 298: 
self.assertEqual(m.rfind(b'one', 0, -1), 8)
C:\Programs\Python38\lib\test\test_mmap.py: 299: 
self.assertEqual(m.rfind(b'one', 0, -2), 0)
C:\Programs\Python38\lib\test\test_mmap.py: 300: 
self.assertEqual(m.rfind(b'one', 1, -1), 8)
C:\Programs\Python38\lib\test\test_mmap.py: 301: 
self.assertEqual(m.rfind(b'one', 1, -2), -1)
C:\Programs\Python38\lib\test\test_mmap.py: 302: 
self.assertEqual(m.rfind(bytearray(b'one')), 8)
C:\Programs\Python38\lib\test\test_socket.py: 313:         i = 
methodname.rfind('.')
C:\Programs\Python38\lib\test\test_urllib2.py: 398:             code = 
action[action.rfind(" ")+1:]
C:\Programs\Python38\lib\urllib\parse.py: 384:         i = url.find(';', 
url.rfind('/'))
C:\Programs\Python38\lib\urllib\request.py: 2083:         semi = 
type.rfind(';')
C:\Programs\Python38\lib\warnings.py: 260:         i = category.rfind(".")
C:\Programs\Python38\lib\zipfile.py: 292:     start = 
data.rfind(stringEndArchive)
C:\Programs\Python38\lib\zipimport.py: 384:             pos = 
data.rfind(STRING_END_ARCHIVE)
Hits found: 136
(Hint: right-click to open locations.)


-- 
Terry Jan Reedy




More information about the Python-ideas mailing list