Codecademy Forums

FAQ: Code Challenge: String Methods - Substring Between

This community-built FAQ covers the “Substring Between” exercise from the lesson “Code Challenge: String Methods”.

Paths and Courses
This exercise can be found in the following Codecademy content:

FAQs on the exercise Substring Between

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

def substring_between_letters(word, start, end):
mystring = [word.find(start)-1:word.find(end)]:
return mystring
I think this should work but im getting a syntax error.

This worked just fine for me:

Write your substring_between_letters function here:

def substring_between_letters(word, start, end):
s = word.find(start) + 1
e = word.find(end)
if s < 0 or e < 0:
return word
return word[s:e]

Uncomment these function calls to test your tip function:

print(substring_between_letters(“apple”, “p”, “e”))

should print “pl”

print(substring_between_letters(“apple”, “p”, “c”))

should print “apple”

Curious why my code didn’t work. I must be missing something in the fun. Could not solve for ‘pl’

def substring_between_letters(word, start, end):
  if word.find(start) < 0 or word.find(end) < 0:
    return word
  else:
    word[word.find(start)+1:word.find(end)]

Why not just use:

You also forgot the return in your else.

def substring_between_letters(word,start,end):
the_list =
the_end_list =
for i in range(0,len(word)):
if(word [i] == start):
the_list.append(i)
for j in range(len(word)-1,-1,-1):
if(word [j] == end):
the_list.append(j)
return word[the_list[0]:the_list[-1]]
I get a warning that int object is not subscriptable. I am wondering Why cannot I acces my list in the function

How should our function handle other cases, like where the “start” character appears after the “end character”?

For example, should this code:

substring_between_letters(word = "adogb", start  = "b", end = "a")

return “dog”, or simply return the word “adogb”

Another case is if the two arguments appear in the proper order, but only after they appear in the wrong order, like

substring_between_letters(word = "adogbruna", start = "b", end = "a"

Should this print “dog”, “run”, or the word?

Substring Between

print (substring_between_letters("adogbruna", "b", "a"))
# adogbruna
print (substring_between_letters("dogbruna", "b", "a"))
# run

The first example returns the full word because a comes before b, and we cannot have the end at the beginning.

The second example we remove the starting a, and get the result we expect since a is at the end, and b does precede it.

Similarly, your first example should also return the full word. Switch the a and b around and it will return dog.

1 Like
#with .find() method (super sloppy. System's answer was much better formatted)
def substring_between_letters(word, start, end):
  answer = word[word.find(start) + 1 : word.find(end)]
  if word.find(end) == -1:
    return word
  elif word.find(start) == -1:
    return word
  else:
    return answer
#Without .find() method
# Write your substring_between_letters function here:

def substring_between_letters(word, start, end):
  start_value = 0
  end_value = 0
  
  while start_value < len(word):
    if word[start_value] != start:
      start_value += 1
    else: 
      break
 
  while end_value > -len(word):
    if word[end_value] != end:
      end_value += -1
    else: 
      break
      
  if start_value == len(word):
    return word
  elif end_value == -len(word):
    return word
  else:
    return word[start_value + 1: end_value]
  
# Uncomment these function calls to test your function:
print(substring_between_letters("apple", "p", "e"))
# should print "pl"
print(substring_between_letters("apple", "p", "c"))
# should print "apple"```

This is the mot simple version I could think of:

def substring_between_letters(word, start, end):
  if start not in word or end not in word:
    return word
  else:
    return word[word.find(start)+1:word.find(end)]
1 Like

A few questions on this one:

  1. Why use find instead of .index?

  2. I tried the following boolean to achieve the return word if start or end are not in the string. It seems to always come back true. But if I remove the or condition and just use if start not in word then returns false and moves on.

def substring_between_letters(word,start,end):
  if start or end not in word:
    return print(word)
  else:
    startPoint = word.index(start)
    endPoint = word.index(end)
    return print(word[startPoint+1:endPoint])
#Uncomment these function calls to test your function:
print(substring_between_letters("apple", "p", "e"))
  1. Why does the following code print “None” as well as the expected result?
def substring_between_letters(word, start, end):
  start_point = word.find(start)
  end_point = word.find(end)
  print(start_point, end_point)
  if start_point == -1 or end_point == -1:
    return print(word) 
  else: 
    return print(word[start_point+1 : end_point])
# Uncomment these function calls to test your tip function:
print(substring_between_letters("apple", "p", "e"))
# should print "pl"
print(substring_between_letters("apple", "p", "c"))
# should print "apple"
  1. They are the same, except that str.find() returns -1 if the string is not found, and is only available for strings, while obj.index() throws an error if the argument is not found, and is available to lists and other subscriptable iterables.

  2. not takes precedence over or, so the expression is parsed as:
    if start or (end not in word):, and assuming that start is anything with a truth value of True (i.e. is not False, 0 (zero), an empty container (list,string, tuple, dictionary), or any expression that evalates to one of those), it will further parse to if True or anything_else:, which will always return True.

  3. The function print() evaluates the expression within its parentheses, and then sends the resulting value as a stream of text to the default i/o device, generally the screen. But (as with every Python function having no explicit return starement), it returns the value None.
    Remember:

  • We print() values that we want to see

  • We return values that Python needs to use (to assign to a variable, perhaps, or to send to another function.)

So basically it only evaluates one statement at a time. If I wrote

if start or end in word

Would it always evaluate to True?

I.e. ‘start’ is never evaluated as whether or it is in word.

For instance:

if start not in word or end not in word:

appears to work and I’m guessing:

if start in word or end in word: 

would also work.

but would the following code break because of the “not” priority?

if start not in word or end in word:

So this is because there are two print statements in the function one of which will always be false and thereby return None?

Thanks!!!

The second operand will not be evaluated unless start cannot be coerced to True.


1 or 0     => 1
'a' or ''  => a
{} or []   => [] 
[] or {}   => {}

Correct.

This would be a case for AND where both operands must satisfy their conditional.


Membership is not precluded by truthiness…

>>> x = [(), ()]
>>> () in x
True
>>> 

This is a gotcha in strings…

>>> '' in 'string'
True
>>> 

In fact there are seven empty strings in that string.

>>> 'string'.count('')
7
>>> 'string'.find('')
0
>>>

This suggests the first test might be to test against the alpha set.

start.isalpha()
end.isalpha()

It would make logical sense when the end string is not in the target for the return to begin at the start string, assuming it is in the target.

pple
1 Like

No!

in and not in are of equal precedence (note that the table in this link shows precedence ordered from least to greatest), so consequently the expression is parsed:

if (start not in word) or (end in word):
…and then evaluated from left to right.

So if start not in word returns True, evaluation ceases, and the if block is executed. If that expression returns False, then end in word is evaluated. If it returns True, the if condition returns True and the if block is executed. If end in word returns False, the if block is skipped.

  • Remember that the expression x or y will behave as you expect only if both x and y are expressions that are guaranteed to return True or False.

  • In general, is is best not to use or as a type of iterable (or a shopping list): if (x or y or z) in str: It is much safer to use if x in str or y in str or z in str:

( … all of the above: ditto with and.)


The problem with
return print(word[start_point+1 : end_point])

… is that is evaluated like this:
return print(something)

  • So to know what to return, Python must evaluate the expression following return: print(something).

  • That means that the expression something is evaluated, and its value returned to the function print().

  • That function does its job, and the value returned by something is sent to the screen as a stream of text. The function print() has executed (printed to the screen), but it returns None. That is its nature: it prints, it does not return (and, in Python, that means it returns None.)

  • So the expression return print(word[start_point+1 : end_point]) ultimately parses to

  • return None (although something is printed in the meantime).

1 Like
def substring_between_letters(word, start, end):
    start = word.find(start)
    end = word.find(end)
    if start and end != -1:
        #print(word[start + 1 : end])
        return word[start + 1: end]
    else:
        return word

One issue I see with that approach is when start and end are the same letters.

substring_between_letters('mountain','n','n')

The return is ''


Played around with the code to work past this issue…

def substring_between_letters(word, start, end):
   before = word.find(start) + 1
   if before == 0:
     return word
   after = word[before:].find(end)
   if after == -1:
     return word
   return word[before : after + before]

print (substring_between_letters('mountain','n','n'))    # tai

what is wrong with my code?
keep present this message, but the parameters are exactly the same