Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

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():

Python
>>> s = 'spam ham clam jam'
>>> s.count('am')
4
>>> s.count('am', 0, 9)
2

Here’s how to use str.endswith():

Python
>>> 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():

Python
>>> 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():

Python
>>> 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():

Python
>>> 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():

Python
>>> 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():

Python
>>> 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.

Avatar image for davidnierman93

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?

Become a Member to join the conversation.