Find and Seek
In this lesson, you’ll explore string methods that provide various means of searching the target string for a specified substring.
Each method in this group supports optional <start>
and <end>
arguments. These are interpreted as for string slicing: the action of the method is restricted to the portion of the target string starting at character position <start>
and proceeding up to but not including character position <end>
. If <start>
is specified but <end>
is not, then the method applies to the portion of the target string from <start>
through the end of the string.
These are find and seek methods:
str.count(<sub>[, <start>[, <end>]])
str.endswith(<sub>[, <start>[, <end>]])
str.startswith(<sub>[, <start>[, <end>]])
str.find(<sub>[, <start>[, <end>]])
str.rfind(<sub>[, <start>[, <end>]])
str.index(<sub>[, <start>[, <end>]])
str.rindex(<sub>[, <start>[, <end>]])
Here’s how to use str.count()
:
>>> s = 'spam ham clam jam'
>>> s.count('am')
4
>>> s.count('am', 0, 9)
2
Here’s how to use str.endswith()
:
>>> s = 'baconsausage'
>>> s.endswith('age')
True
>>> s.endwith('ages')
False
>>> s.endswith('ons', 0, 9)
False
>>> s.endswith('ons', 0, 6)
True
Here’s how to use str.startswith()
:
>>> s = 'baconsausage'
>>> s.startswith('bac')
True
>>> s.startswith('saus')
False
>>> s.startswith('saus', 5)
True
>>> s.startswith('saus', 5, 7)
False
Here’s how to use str.find()
:
>>> s = 'spam bacon egg sausage'
>>> s.find('egg')
11
>>> s.find('spam')
0
>>> s.find('lobster')
-1
>>> s.find('egg', 9, 20)
11
>>> s.find('egg', 9)
11
>>> s.find('egg', 5, 10)
-1
Here’s how to use str.rfind()
:
>>> s = 'spam bacon spam spam egg spam'
>>> s.find('spam')
0
>>> s.rfind('spam')
25
>>> s.rfind('spam', 8, 15)
11
>>> s.rfind('spam', 8, 10)
-1
Here’s how to use str.index()
:
>>> s = 'spam bacon spam spam egg spam'
>>> s.index('spam')
0
>>> s.index('spm')
Traceback (most recent call last):
File "<input>", line 1, in <module>
s.index('spm')
ValueError: substring not found
Here’s how to use str.rindex()
:
>>> s = 'spam bacon spam spam egg spam'
>>> s.rindex('spam')
25
>>> s.rindex('spm')
Traceback (most recent call last):
File "<input>", line 1, in <module>
s.rindex('spm')
ValueError: substring not found
00:00 For this video, I’m going to show you find and seek methods. These methods provide various means of searching the target string for a specified substring.
00:09
Each of these methods supports optional start
and end
arguments. These work the same way as they did for string slicing. If you enter in a start
value, it’ll start searching from that position and up to but not including the value of the end
position. In this case, if start
is specified but end
is not, the method will be applied from the start
value all the way to the end of the string. For the method .count()
, it’s going to return the number of non-overlapping occurrences of that substring within the string.
00:42
Create a string. In this case, we’re using the word 'spam'
and other words that rhyme with it. And what you’re going to do is, using the .count()
method, search within the string s
using a substring. So in this case, the substring is going to be the letters 'am'
. As you can see here, the optional arguments of start
and end
are interpreted in slice notation, that you practiced in the earlier videos. In this case, leave those optional arguments out. And here, you can see it found 4
versions of that substring throughout there.
01:16
If you were to apply .count()
again, but this time using the optional substring, let’s say you went from index 0
up to index 9
.
01:28
In that case, it only found 2
instances because it was cut off before the end of 'clam'
or 'jam'
. So using the same style of slicing, you can limit where you’re searching within your strings.
01:43
Next up, .endswith()
. It determines whether the target string is going to end with the given substring. It’s going to return a True
if it does end with the specified suffix or False
if otherwise.
01:56
For this one, create a new string of 'baconsausage'
. And what you want to do with your .endswith()
is check to see if the string ends with the letters 'age'
. In that case, as you can see, it’s going to return a bool
of True
, and False
otherwise.
02:16
And you can see the same optional start
and end
slicing techniques you can use also. So in this case, that’s True
. But you could also check
02:27
if it was plural. That’s False
. Here we are with our same string s
,
02:37
and this time you want to check if the string 'ons'
is the end, or suffix, of the string slice that you’re setting up, from 0
index all the way up to index 9
.
02:53
And that would be False
, because it ends at 0
, 1
, 2
, 3
, 4
, 5
.
03:04
Let’s check up to 6
. Remember that the ending index that you’re entering in will create a slice that goes up to but does not include that actual index.
03:15
This is creating a substring—a slice, if you will—in this case, it would be 'bacons'
. And it’s checking right up to the end of that. In this case, it went too far. It was checking all the way up to here.
03:30
Next, is the reverse, which is .startswith()
. It determines whether the target string starts with a given substring. Again, it will return True
if the string starts with the specified prefix, or False
otherwise. .startswith()
, again, it’s going to look at the substring—in this case, a prefix—and we could say, “Okay, does it begin with 'bac'
?” And that would be True
.
04:00
Versus starting with 'sausage'
or 'saus'
.
04:05
The comparison is going to be restricted by the substring that you indicate with your start and end points also. So if you wanted to look for 'saus'
, then you’d have to have your .startswith()
begin where that starts. In that case, that’d be at index 5
, the sixth character. Again, the end
is optional. So we can just say “From this point on,” and that would be True
.
04:32
Whereas if you were to cut it short, in this case ending only with the first two characters, since it wouldn’t contain the entire substring, it would return False
.
04:44
For .find()
it’s going to search the target string for a given substring. In the case of .find()
, instead of a True
or False
it’s going to return the lowest index where the substring is found. To try out .find()
, create a new string s
,
05:03
this time with the words 'spam bacon egg sausage'
. To try out the method, start with s.find()
, and then enter in the substring, and you’ll see the substring 'egg'
is first found at index 11
.
05:22
Versus 'spam'
, which would be at the beginning—the very first index of 0
. If something is not found, like the substring 'lobster'
, it will return -1
.
05:38
Again, you can use start and end points to limit where the search will begin and end. So if you were to begin at index 9
and go to index 20
, in this case, it would still find that first index of 11
because it’s within the range that you’ve set.
05:56
You can leave out the end point, and it will simply start and go all the way to the end. If you were to create a slice of that string with a start and end point that doesn’t include your substring, you’ll again get a -1
, indicating “Failure, not found.”
06:16
The method .rfind()
searches the target string for the given substring, but it starts its search from the right side, or the end, of your string.
06:27
It’s going to return the highest index value where the substring is found. For .rfind()
, create a new string. This string is going to have multiple instances of the word 'spam'
in it.
06:42
Try it out with the .find()
method again. It would find it at index 0
. Versus .rfind()
, it would find it all the way out here at index 25
.
06:53
And .rfind()
has the same start and end points with the same return of a integer value. So if you were to limit the starting point to 8
and go all the way to 15
, it would return index 11
in that case. And if it’s not found,
07:21
a -1
. .index()
searches the target string for a given substring again. The primary difference between it and .find()
is instead of returning -1
, it will raise an exception. Let’s explore these two, starting with .find()
. It returns the lowest index, and -1
on a failure, for .find()
.
07:48
.index()
returns the lowest index but raises a ValueError
when the substring’s not found. Okay. So s
—we’ll use this version of s
that has 'spam bacon spam spam egg spam'
.
08:02
And so s.index('spam')
is going to return index 0
, the very beginning. Let’s say we were looking for just 'spm'
. There it says the ValueError: substring not found
. So instead of a -1
, you’ll get this exception.
08:22
.rindex()
works the same way as .index()
, except for it starts at the end, searching from the right for the target substring within the string.
08:32 And in the same way, it will raise an exception if that substring is not found.
08:40
In the same way that there is an .rfind()
, there is an .rindex()
. And in its case, it would do the same thing. So here, .rindex()
would return 25
, the highest index where it’s found. The first one on the right, if you will. And in the same way, .rindex()
, if the string is not within, that substring would return a ValueError
. Great!
09:06 Now that you’ve done a little bit of find and seek, in the next video you’ll do character classification.
Become a Member to join the conversation.
davidnierman93 on Dec. 14, 2020
When would you use index and rindex instead of find and rfind?
In other words, can I see a use case where returning an error is preferred over returning -1? and vice versa?