Verifying the ending of a string is a common task in Python, useful for validating filenames, parsing URLs, checking data formats, or categorizing text. Python offers several ways to achieve this, from the simple str.endswith() method for exact matches to the more powerful re.search() for pattern matching (like checking for any number).
This guide demonstrates how to effectively check if a string ends with a specific substring, any number, or one of several possible suffixes.
Check if String Ends With Specific Substring
Goal: Determine if a string terminates with an exact sequence of characters.
Using str.endswith() (Recommended)
The built-in str.endswith() method is the most direct and readable way to check for a specific suffix.
filename = "document_final_v2.docx"
target_suffix = ".docx"
ends_with_docx = filename.endswith(target_suffix)
print(f"String: '{filename}'")
print(f"Ends with '{target_suffix}'? {ends_with_docx}") # Output: True
ends_with_pdf = filename.endswith(".pdf")
print(f"Ends with '.pdf'? {ends_with_pdf}") # Output: Falsestring.endswith(suffix): ReturnsTrueifstringends exactly with the characters insuffix, otherwiseFalse. It's case-sensitive by default.
Using String Slicing
You can achieve this manually with slicing, but it's less readable than endswith().
filename = "document_final_v2.docx"
target_suffix = ".docx"
ends_with_slice = filename[-len(target_suffix):] == target_suffix
print(f"String: '{filename}'")
print(f"Ends with '{target_suffix}' (slicing)? {ends_with_slice}") # Output: True
long_suffix = "very_long_suffix.docx"
safe_check = len(filename) >= len(long_suffix) and filename[-len(long_suffix):] == long_suffix
print(f"Ends with '{long_suffix}' (safe slice)? {safe_check}") # Output: Falsefilename[-len(target_suffix):]: Slices the string starting from the position calculated by the negative length of the suffix up to the end.- Requires checking length first if the suffix might be longer than the string.
endswith()handles this automatically.
Check if String Ends With One of Multiple Substrings
Goal: Determine if a string terminates with any of the suffixes provided in a collection (like a tuple or list).
Using str.endswith() with a Tuple (Recommended)
The endswith() method conveniently accepts a tuple of suffixes as its first argument. It returns True if the string ends with any one of the strings in the tuple.
url = "https://example.com/image.png"
image_extensions = ('.jpg', '.jpeg', '.png', '.gif') # Suffixes in a tuple
is_image_url = url.endswith(image_extensions)
print(f"URL: '{url}'")
print(f"Image Extensions: {image_extensions}")
print(f"Is image URL? {is_image_url}") # Output: True (ends with .png)
url_doc = "https://example.com/report.docx"
is_image_url_doc = url_doc.endswith(image_extensions)
print(f"URL: '{url_doc}'")
print(f"Is image URL? {is_image_url_doc}") # Output: FalseThis is the most concise and idiomatic way to check against multiple possible endings.
Using any() with a Generator Expression
You can achieve the same result using any() and a generator expression, checking endswith() for each suffix individually. This is more verbose but demonstrates the underlying logic.
url = "https://example.com/image.png"
image_extensions = ('.jpg', '.jpeg', '.png', '.gif')
is_image_any = any(url.endswith(suffix) for suffix in image_extensions)
print(f"URL: '{url}'")
print(f"Is image URL (any)? {is_image_any}") # Output: TrueCheck if String Ends With a Number (Any Digit)
Goal: Determine if the very last character(s) of a string are numeric digits (0-9).
Using Regular Expressions (re.search()) (Recommended)
Regular expressions are ideal for pattern matching like "one or more digits at the end". We use re.search() with a pattern ending in $, which anchors the match to the end of the string.
import re # Required import
string1 = "file_version_123"
string2 = "file_version_abc"
string3 = "version4"
string4 = "" # Empty string
pattern = r'\d+$'
match1 = re.search(pattern, string1)
print(f"String: '{string1}'")
if match1:
print(f"Ends with number? Yes (Match: '{match1.group()}')") # Output: Yes (Match: '123')
else:
print("Ends with number? No")
match2 = re.search(pattern, string2)
print(f"String: '{string2}'")
if match2:
print(f"Ends with number? Yes (Match: '{match2.group()}')")
else:
print("Ends with number? No") # Output: No
match3 = re.search(pattern, string3)
print(f"String: '{string3}'")
if match3:
print(f"Ends with number? Yes (Match: '{match3.group()}')") # Output: Yes (Match: '4')
else:
print("Ends with number? No")
match4 = re.search(pattern, string4)
print(f"String: '{string4}'")
if match4:
print(f"Ends with number? Yes (Match: '{match4.group()}')")
else:
print("Ends with number? No") # Output: Nore.search(pattern, string): Returns a match object if the pattern is found anywhere,Noneotherwise.r'\d+$': The pattern.\dmatches any digit.+means "one or more" of the preceding element (\d).$anchors the match to the very end of the string.if match1:: Checks ifre.searchreturned a match object (truthy) orNone(falsy).match1.group(): If a match exists, this returns the actual matched substring (the number at the end).
Using Indexing and str.isdigit()
You can check if the last character is a digit. This only works reliably if you expect exactly one digit at the end or don't care about preceding non-digits.
def ends_with_single_digit(input_str):
"""Checks if the very last character is a digit."""
return bool(input_str and input_str[-1].isdigit())
string1 = "item_code_5"
string2 = "item_code_12" # Ends in a digit, but method only checks the last one
string3 = "item_code_X"
string4 = ""
print(f"'{string1}': Ends with single digit? {ends_with_single_digit(string1)}") # Output: True
print(f"'{string2}': Ends with single digit? {ends_with_single_digit(string2)}") # Output: True
print(f"'{string3}': Ends with single digit? {ends_with_single_digit(string3)}") # Output: False
print(f"'{string4}': Ends with single digit? {ends_with_single_digit(string4)}") # Output: Falseinput_str[-1]: Accesses the last character. Negative indexing counts from the end..isdigit(): Checks if that single character is a digit.bool(input_str and ...): Safely handles empty strings (an empty string is falsy, so the check short-circuits).- Limitation: This doesn't verify if there are multiple digits at the end (like in
item_code_12) or handle cases where non-digits precede the final digit. Regex (\d+$) is better for "ends with one or more digits".
Check if String Ends With Specific Number(s) (Using endswith)
If you need to check if a string ends with a specific number represented as a string, endswith() is the appropriate tool.
log_entry = "transaction_id_12345"
error_code = "process_failed_99"
ends_with_12345 = log_entry.endswith("12345")
print(f"'{log_entry}': Ends with '12345'? {ends_with_12345}") # Output: True
error_codes = ("_99", "_101", "_500")
is_known_error = error_code.endswith(error_codes)
print(f"'{error_code}': Ends with {error_codes}? {is_known_error}") # Output: TrueCase-Insensitive Checks
endswith(): Does not have a built-in case-insensitivity flag. You must convert both the string and the suffix(es) to the same case first:filename = "Report.PDF" suffixes = (".pdf", ".docx") match = filename.lower().endswith(tuple(s.lower() for s in suffixes)) print(f"'{filename}' ends with {suffixes} (insensitive)? {match}") # Output: Truere.search(): Use there.IGNORECASEflag:import re text = "Image.JPEG" match_re = re.search(r'\.jpeg$', text, flags=re.IGNORECASE) print(f"'{text}' ends with '.jpeg' (regex insensitive)? {bool(match_re)}") # Output: True
Conclusion
Checking string endings in Python involves choosing the right tool:
- For exact, specific suffixes: Use
str.endswith(suffix). - For checking against multiple specific suffixes: Use
str.endswith((suffix1, suffix2, ...))with a tuple. - For checking if the string ends with any number (one or more digits): Use
re.search(r'\d+$', string). - For checking if the very last character is a digit: Use slicing and
string[-1].isdigit()(handle empty strings). - For case-insensitive checks: Convert strings to lowercase/uppercase before using
endswith(), or use there.IGNORECASEflag withre.search().
Select the method that precisely matches the pattern or suffix you need to verify at the end of your string.