Skip to main content

Command Palette

Search for a command to run...

Python's String Methods Turned Out to Be a Cheat Code

Updated
6 min readView as Markdown
Python's String Methods Turned Out to Be a Cheat Code
D

A dedicated Computer Engineering graduate from SCET. Throughout my academic journey, I navigated the dynamic landscape of education during the challenging Covid era, which instilled in me resilience and adaptability. My experience in the field of Data Engineering spans across Transact SQL, MS SQL Server, Agile Methodologies, and a foundational understanding of Azure Data Factory and various cloud services. These experiences have not only honed my technical acumen but also reinforced my capacity to thrive in diverse and evolving environments.

My current pursuits reflect a keen interest in expanding my knowledge in both DevOps and Cloud Engineering. Alongside these technical endeavors, I'm fervently learning Full Stack Web Development from the ground up, eager to explore the intricate interplay of front-end and back-end systems.

Embracing a holistic approach to problem-solving, I'm delving into the intricacies of System Design, striving to develop comprehensive and efficient solutions within the IT industry. Building on approximately 6 months to 1-year of hands-on industry experience, I'm driven to continuously enhance my skill set, contributing meaningfully to the technological landscape.

Beyond the realms of technology, I find solace in capturing the ephemeral beauty of sunsets through photography, letting the time freeze those breathtaking moments. Music is my constant companion, offering relaxation and inspiration. As an avid cricket enthusiast, the game brings camaraderie and excitement.

I'm always open to connecting with fellow professionals, learning from shared experiences, and contributing to the ever-evolving tech sphere. Let's connect and explore the limitless possibilities together!

Up to this point I've been doing a lot of string work manually: indexing, slicing, writing my own loops to check things. Turns out Python ships a whole toolbox of ready-made string methods that handle most of this for me, and once I saw the list, a lot of code I'd have written from scratch stopped being necessary.

A few of these functions (len, max, min, sorted) actually work across multiple data types, not just strings. The rest are string-specific methods, called with a dot, like s.upper().

Function/method What it does
len(s) length of the string (also works on lists, tuples, etc.)
max(s) / min(s) character with the highest/lowest underlying code point
sorted(s) characters sorted ascending, or descending with reverse=True
.capitalize() first character uppercase, everything else lowercase
.title() first character of every word uppercase
.upper() / .lower() whole string to upper/lowercase
.swapcase() flips the case of every character
.count(x) how many times x appears
.find(x) index of x, or -1 if it's not there
.index(x) index of x, raises an error if it's not there
.startswith(x) / .endswith(x) whether the string starts/ends with x
.format(...) inserts values into {} placeholders
.isalnum() / .isalpha() / .isdigit() checks whether the string is letters+digits, letters only, or digits only
.isidentifier() whether the string would be a legal variable name
.split(sep) splits into a list, on whitespace by default
.join(list) joins a list of strings, using this string as the glue
.replace(old, new) replaces every occurrence of old with new
.strip() removes leading/trailing whitespace

That table is a lot to take in at once, so here's each group with actual code.

Common functions (not string-exclusive)

s = "welcome to python"

print(len(s))              # 17
print(max(s))               # y, highest code point in the string
print(min(s))               # ' ', the space has the lowest code point
print(sorted(s))             # sorted characters, ascending, as a list
print(sorted(s, reverse=True))  # same, but descending

Changing case

s = "welcome to python"

print(s.capitalize())  # Welcome to python
print(s.title())       # Welcome To Python
print(s.upper())       # WELCOME TO PYTHON
print("WELCOME".lower())  # welcome
print("WelCome".swapcase())  # wELcOMB, opposite case for every letter

Worth calling back to the immutability post here: none of these change s itself. Each one returns a brand new string, and the original stays exactly as it was, since strings can't be modified in place.

Searching inside a string

s = "my name is darshan"

print(s.count("a"))    # 3, how many times "a" shows up
print(s.find("a"))     # 4, the index of the first "a"
print(s.find("z"))     # -1, not found, no error
print(s.index("a"))    # 4, same as find here
# print(s.index("z"))  # raises ValueError: substring not found

.find() and .index() do the same job, locating a substring, but they disagree on what happens when nothing's found. .find() quietly returns -1. .index() raises an error instead. Which one to reach for depends on whether you want your code to handle a "not found" case gracefully or treat it as something worth crashing over.

Checking the edges

s = "my name is darshan"

print(s.endswith("shan"))   # True
print(s.startswith("My"))   # False, case-sensitive
print(s.startswith("my"))   # True

Inserting values: format() and f-strings

.format() lets you build a string with placeholders, then fill them in separately.

name = "Darshan"
gender = "male"

s = "My name is {}. I am a {}."
print(s.format(name, gender))
# My name is Darshan. I am a male.

Without extra index numbers, .format() fills placeholders in the order the arguments are given. You can also control that explicitly:

s = "{1} goes with {0}"
print(s.format(gender, name))
# Darshan goes with male... wait, that's wrong on purpose:
# {1} pulls index 1 (name), {0} pulls index 0 (gender)

F-strings do the exact same job with noticeably less ceremony, no method call, no worrying about argument order:

name = "Darshan"
gender = "male"

s = f"My name is {name}. I am a {gender}."
print(s)
# My name is Darshan. I am a male.

Since f-strings reference variables by name directly inside the string, there's no ordering to get wrong. I'll be reaching for f-strings by default going forward in this series, and only using .format() when there's a specific reason to.

Validating the shape of a string

print("darshan123".isalnum())   # True, letters and digits only
print("darshan123".isalpha())   # False, contains digits
print("123".isdigit())          # True
print("1name".isidentifier())   # False, can't start with a digit
print("name_1".isidentifier())  # True

That last one is a nice callback to the identifier rules from a much earlier post. Instead of remembering the rules myself, .isidentifier() just checks them for me.

Splitting and joining

s = "my name is darshan"
words = s.split()          # splits on whitespace by default
print(words)                # ['my', 'name', 'is', 'darshan']

csv_line = "my,name,is,darshan"
print(csv_line.split(","))  # splits on a comma instead

joined = " ".join(words)
print(joined)                # my name is darshan, glued back with spaces

hyphenated = "-".join(words)
print(hyphenated)            # my-name-is-darshan

Cleaning up whitespace

messy = "   my name is darshan   "
print(len(messy))          # includes the extra spaces
print(len(messy.strip()))  # extra leading/trailing whitespace gone

.strip() shows up constantly in real applications, trimming stray whitespace off user input (like an email or password field) before actually using it.

Common mistakes I'd flag here

  • Reaching for .index() when .find() would be safer, and getting an unhandled ValueError when the substring isn't actually there.

  • Forgetting string methods return a new string rather than modifying the original, then being confused when the original variable looks unchanged.

  • Mixing up .format()'s implicit ordering with explicit index numbers, and getting values swapped into the wrong placeholders.

  • Comparing .startswith()/.endswith() results without accounting for case sensitivity.

Quick recap

  • len, max, min, and sorted aren't string-exclusive, they work across several data types.

  • Case methods (capitalize, title, upper, lower, swapcase) all return new strings, never modify the original.

  • .find() returns -1 on a miss, .index() raises an error, pick based on how you want failures handled.

  • .format() and f-strings both insert values into a string; f-strings are shorter and don't depend on argument order.

  • .isalnum(), .isalpha(), .isdigit(), and .isidentifier() are quick validity checks worth knowing instead of writing manual character checks.

  • .split() and .join() are inverses of each other: one breaks a string into a list, the other glues a list back into a string.

What's next

Next up, I'm putting some of these string tools to work on three small practice problems, before moving on to data structures like lists and tuples.

Bite-Sized Python: Zero to Modular Code

Part 14 of 16

Learning to code or pivoting into modern software development can feel like wading through an ocean of tutorials. In this series, I document my hands-on journey through Python, breaking down every core concept into plain-English explanations, visual mental models, and ready-to-use code snippets. Whether you are writing your first print() statement or learning how to structure production-ready modular applications, follow along as we build our skills one post at a time.

Up next

Three String Exercises That Made Indexing, Slicing, and Loops Finally Click

Reading about strings is one thing. Actually solving something with them is what made the last few posts in this series feel less like memorized rules and more like usable tools. Here are three small

More from this blog

The Accidental Techie: Darshan Joshi

20 posts

Code creator by day, deep thinker by night✨ weaving bytes and pondering life's algorithms❤

A dedicated Computer Engineering graduate from SCET. Throughout my academic journey, I navigated the dynamic landscape of education during the challenging Covid era, which instilled in me resilience and adaptability. My experience in the field of Data Engineering spans across Transact SQL, MS SQL Server, Agile Methodologies, and a foundational understanding of Azure Data Factory and various cloud services. These experiences have not only honed my technical acumen but also reinforced my capacity to thrive in diverse and evolving environments.

My current pursuits reflect a keen interest in expanding my knowledge in both DevOps and Cloud Engineering. Alongside these technical endeavors, I'm fervently learning Full Stack Web Development from the ground up, eager to explore the intricate interplay of front-end and back-end systems.

Embracing a holistic approach to problem-solving, I'm delving into the intricacies of System Design, striving to develop comprehensive and efficient solutions within the IT industry. Building on approximately 6 months to 1-year of hands-on industry experience, I'm driven to continuously enhance my skill set, contributing meaningfully to the technological landscape.

Beyond the realms of technology, I find solace in capturing the ephemeral beauty of sunsets through photography, letting the time freeze those breathtaking moments. Music is my constant companion, offering relaxation and inspiration. As an avid cricket enthusiast, the game brings camaraderie and excitement.

I'm always open to connecting with fellow professionals, learning from shared experiences, and contributing to the ever-evolving tech sphere. Let's connect and explore the limitless possibilities together!