Strings and f-strings
Text is most of what programs actually handle — names, addresses, messages, file contents, everything a user types. This is the longest lesson in the module, and the f-string section is the single most useful piece of syntax you will learn this week.
Making strings
Single and double quotes work identically:
name = "Priya"
city = 'Pune'
Pick one and stay consistent. The exception is when the text itself contains a quote:
message = "It's raining"
quote = 'She said "hello"'
Use the other kind, and you avoid escaping entirely.
For text spanning several lines, use triple quotes:
address = """42 MG Road
Koregaon Park
Pune 411001"""
print(address)
The line breaks are preserved exactly as typed.
Joining and repeating
first = "Priya"
last = "Sharma"
full = first + " " + last
print(full)
Priya Sharma
+ joins strings. Note the " " — without it you get PriyaSharma. Python
adds nothing you did not ask for.
* repeats:
print("-" * 40)
A quick way to print a separator line.
Adding a string to a number fails:
age = 25
print("I am " + age)
TypeError: can only concatenate str (not "int") to str
This is Python refusing to guess. Did you mean the text "25", or something
numeric? Rather than choose for you, it stops. The fix is the next section.
f-strings
This is the important part.
Put f before the opening quote, and anything inside { } is worked out and
inserted:
name = "Priya"
age = 25
print(f"{name} is {age} years old")
Priya is 25 years old
No +, no converting the number by hand, and — crucially — you can read it. The
sentence looks like the sentence.
Any expression works inside the braces, not just a name:
price = 250
quantity = 3
print(f"Total: {price * quantity} rupees")
print(f"Name in caps: {name.upper()}")
Total: 750 rupees
Name in caps: PRIYA
Formatting inside the braces
After a colon you can say how to display the value. These few are worth memorising:
pi = 3.14159265
print(f"{pi:.2f}") # 3.14 — two decimal places
print(f"{1234567:,}") # 1,234,567 — thousands separators
print(f"{0.856:.1%}") # 85.6% — as a percentage
Combine them for money:
total = 1234567.891
print(f"Total: {total:,.2f}")
Total: 1,234,567.89
That one line replaces a surprising amount of fiddly code.
Alignment, for lining up columns:
for item, cost in [("Tea", 40), ("Coffee", 120), ("Sandwich", 85)]:
print(f"{item:<12}{cost:>6}")
Tea 40
Coffee 120
Sandwich 85
< left-aligns, > right-aligns, ^ centres, and the number is the width. You
have not met for loops yet — they arrive in the next module — so take that
example on trust for now.
A debugging trick
Put = after the expression and Python prints both the expression and its
value:
count = 17
print(f"{count = }")
count = 17
When you are scattering print calls to find a bug, this saves typing the name
twice and guarantees the label matches what is actually printed.
Older styles
You will meet these in existing code:
print("%s is %d years old" % (name, age)) # very old
print("{} is {} years old".format(name, age)) # older
print(f"{name} is {age} years old") # use this
Recognise the first two. Write the third.
Useful methods
A method is a function belonging to a value, called with a dot.
text = " Hello World "
print(text.strip()) # "Hello World" — removes surrounding whitespace
print(text.upper()) # " HELLO WORLD "
print(text.lower()) # " hello world "
print(text.replace("World", "Pune"))
strip() matters more than it looks. Anything a user types or that comes from a
file arrives with stray spaces and newlines, and a trailing space is invisible
while breaking every comparison you make.
Searching and testing:
email = "priya@example.com"
print(email.startswith("priya")) # True
print(email.endswith(".com")) # True
print("@" in email) # True
print(email.find("@")) # 5
print(len(email)) # 17
in is the readable way to ask whether text appears inside other text. Prefer
it to find() unless you need the position.
Splitting and joining are a pair you will use constantly:
csv_line = "Priya,Sharma,Pune"
parts = csv_line.split(",")
print(parts)
rejoined = " | ".join(parts)
print(rejoined)
['Priya', 'Sharma', 'Pune']
Priya | Sharma | Pune
split turns a string into a list; join turns a list back into a string. Note
that join is called on the separator, which reads backwards until you have
done it twice.
Indexing and slicing
Positions start at zero:
word = "Python"
print(word[0]) # P
print(word[1]) # y
print(word[-1]) # n — last character
print(word[-2]) # o — second from last
Negative indexes count from the end, so [-1] is the last character without
needing to know the length.
Slicing takes a range, [start:end], where end is not included:
word = "Python"
print(word[0:3]) # Pyt
print(word[:3]) # Pyt — from the beginning
print(word[3:]) # hon — to the end
print(word[::-1]) # nohtyP — reversed
That exclusive end is the single most common off-by-one confusion in Python. The
way to hold it: word[0:3] gives you three characters, starting at zero. The
length of the slice is end - start.
Strings cannot be changed
word = "Python"
word[0] = "J"
TypeError: 'str' object does not support item assignment
Strings are immutable. You cannot modify one in place. Every method that appears to change a string actually returns a new one:
text = "hello"
text.upper()
print(text) # still "hello"
text = text.upper()
print(text) # now "HELLO"
That first text.upper() computed "HELLO" and threw it away, because nothing
caught the result. This catches everybody once. If a string method seems to have
done nothing, check that you assigned its result.
Escape characters
print("Line one\nLine two") # \n is a newline
print("Name:\tPriya") # \t is a tab
print("She said \"hello\"") # \" is a literal quote
print("C:\\Users\\priya") # \\ is a literal backslash
For Windows paths, a raw string is easier — the r switches escaping off:
print(r"C:\Users\priya\new_file")
Without the r, that \n in \new_file would become a newline.
Practice
- Ask for a first and last name (hard-code them for now), and print a greeting using an f-string.
- Given
price = 2499.5, printPrice: ₹2,499.50using f-string formatting only — no manual rounding. - Take
" PRIYA SHARMA "and produce"Priya Sharma"using string methods. You will needstrip()and one more; find it withdir(""). - Given
email = "priya.sharma@example.com", extract the username before the@two ways: once withsplit(), once with slicing andfind(). - Write a function-free "password strength" check: given
password = "hello123", print its length, whether it contains a digit (tryany(c.isdigit() for c in password)), and whether it is longer than 8 characters. - Prove immutability to yourself: call
.upper()on a string without assigning the result, print it, and confirm nothing changed.
Next: booleans, None, and the values Python quietly treats as false.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship