Ga naar hoofdinhoud

Zoek en vervang in Python-strings: in, .find(), .index(), .count() en .replace()

Praktische patronen voor het zoeken, tellen en vervangen van substrings in modern Python.
· 8 min lezen

Verken met AI

Het is gebruikelijk om naar .find() of .index() te grijpen om te checken of tekst in een string voorkomt—om vervolgens vreemd gedrag tegen te komen, zoals een ValueError of een gemiste match aan het begin van de string. Hoofdlettergevoeligheid, off-by-one slice-grenzen en het feit dat er geen .contains()-methode op str bestaat, maken het verwarrend. De oplossing is simpel: gebruik het juiste gereedschap. We gebruiken de in-operator voor bestaanstests, .find()/.index() voor posities, .count() voor tellingen en .replace() voor vervangingen—plus een paar Unicode-veilige technieken wanneer hoofdletterongevoeligheid belangrijk is.

Hoe Python zoekt naar substrings

De tekststrings van Python zijn Unicode. Substring-bewerkingen zijn standaard hoofdlettergevoelig en in C geïmplementeerd voor snelheid. De meest directe manier om te testen of tekst in een string voorkomt is de in-operator, die een Booleaan teruggeeft via de __contains__()-implementatie van de string. Als je posities of aantallen nodig hebt, gebruik je de daarvoor bestemde str-methoden. Optionele parameters start en end volgen slice-semantiek: start is inclusief; end is exclusief.

Bevatting met in

Gebruik "needle" in haystack wanneer je alleen wilt weten of de substring bestaat. Het is leesbaar en voorkomt gedoe met indexen.

text = "Banana bread"
print("ban" in text)   # False (case-sensitive)
print("Ban" in text)   # True

Voor hoofdletterongevoelige checks, normaliseer je beide kanten. .casefold() is meer Unicode-bewust dan .lower() en is mijn standaard voor case-insensitief vergelijken.

pattern = "ban"
print(pattern.casefold() in text.casefold())  # True
  • Wanneer te gebruiken: snelle bestaanstests, invoervalidatie, lijsten filteren.
  • Randgeval: "" in s is altijd True (de lege string zit in elke string).

str.find()-methode

Syntaxis

str.find() retourneert de laagste index van de substring, of -1 als deze niet wordt gevonden. Optionele start en end beperken de zoekopdracht.

s.find(substring, start=0, end=len(s))

Voorbeelden en gebruikssituaties

Gebruik .find() wanneer je de positie nodig hebt en een “niet gevonden”-waarde kunt afhandelen zonder exceptions.

tagline = "Ship fast. Fix faster."
print(tagline.find("fast"))         # 5
print(tagline.find("fast", 6))      # 16
print(tagline.find("slow"))         # -1

Schrijf niet if s.find(sub): om bestaan te checken. Als de match op index 0 staat, is de voorwaarde falsy.

name = "Alice"
if name.find("A"):         # Wrong: 0 is Falsey
    print("Found A")       # Will not run
if name.find("A") != -1:   # Correct
    print("Found A")

str.index()-methode

Syntaxis

.index() spiegelt .find() maar werpt een ValueError wanneer de substring ontbreekt.

s.index(substring, start=0, end=len(s))

Voorbeelden en wanneer je het kiest

Gebruik .index() wanneer de substring móét bestaan en een exception de juiste foutmodus is.

product = "USB-C Cable"
print(product.index("Cable"))  # 6

try:
    product.index("HDMI")
except ValueError:
    print("Required label missing")

str.count()-methode

Syntaxis

.count() geeft het aantal niet-overlappende voorkomens terug. Accepteert ook start- en end-grenzen.

s.count(substring, start=0, end=len(s))

Voorbeelden en randgevallen

Gebruik .count() voor snelle tellingen zonder regex.

log_line = "ERROR: timeout. ERROR: retry. ERROR: gave up."
print(log_line.count("ERROR"))     # 3
print(log_line.count("WARN"))      # 0

Speciaal geval: de lege string.

print("abc".count(""))   # 4 (len(s) + 1)

str.replace()-methode

.replace() retourneert een nieuwe string waarin voorkomens van old zijn vervangen door new. Gebruik count om het aantal vervangingen te beperken.

s.replace(old, new, count=-1)

Substrings vervangen

De methode is niet in-place; ze retourneert een kopie.

message = "The red house is between the blue house and the old house"
print(message.replace("house", "car"))
# The red car is between the blue car and the old car

print(message.replace("house", "car", 2))
# The red car is between the blue car and the old house

Hoofdletterongevoelig vervangen

Voor hoofdletterongevoelige vervangingen met behoud van hoofdletterpatronen gebruik je re.sub() met re.IGNORECASE, of normaliseer je met .casefold() als je de oorspronkelijke casing niet hoeft te behouden.

Hoofdletterongevoelig matchen met .casefold()

.casefold() biedt agressieve, Unicode-bewuste casenormalisatie en verdient de voorkeur boven .lower() voor case-insensitieve checks.

query = "straße"           # German 'straße'
text  = "STRASSE und mehr" # Uppercase variant
print(query.casefold() in text.casefold())  # True

Aanverwante tools voor prefixen en suffixen

Bij bekende begin- of eindteksten gebruik je de speciale methoden—die zijn sneller en duidelijker dan slicing of regex:

  • s.startswith(prefix) en s.endswith(suffix) (accepteren tuples voor meerdere opties)
  • s.removeprefix(prefix) en s.removesuffix(suffix) (Python 3.9+)
filename = "draft_report_v2.pdf"
print(filename.removeprefix("draft_"))  # report_v2.pdf
print(filename.endswith((".pdf", ".docx")))  # True

Werken met Pandas-kolommen

Als je veel strings in een DataFrame-kolom doorzoekt, gebruik dan gevectoriseerde stringmethoden. Zet regex=False om letterlijke tekst te matchen.

import pandas as pd

cities = pd.Series(["New York", "Yorktown", None, "Toronto"], dtype="string")
mask = cities.str.contains("York", regex=False, na=False)
print(mask.tolist())  # [True, True, False, False]

Notities:

  • Standaard is regex=True, dus speciale tekens zoals . matchen elk teken tenzij je regex uitschakelt.
  • Ga om met nulls via na=.... Met StringDtype zijn missende waarden standaard False in de mask.

Veelvoorkomende valkuilen en randgevallen

  • Geen .contains() op str: gebruik "sub" in s. "abc".contains("a") geeft een AttributeError.

  • .find() truthiness: index 0 is falsy; vergelijk met != -1 of gebruik liever in voor bestaan.

  • .index() gooit een exceptie: handel ValueError af als de substring kan ontbreken.

  • Lege substring: "" in s is True; s.find("") retourneert 0; s.count("") is len(s)+1.

  • Hoofdlettergevoeligheid: alle operaties zijn hoofdlettergevoelig tenzij je normaliseert of regex-flags gebruikt.

  • Bytes vs. tekst: mix bytes en str niet in zoekopdrachten; decodeer of codeer om types te laten overeenkomen.

  • Substring-semantiek: "ab" in "cat,bat" is False ook al komen "a" en "b" afzonderlijk voor—matches moeten aaneengesloten zijn.

Praktische voorbeelden om te draaien

Deze korte snippets tonen de juiste patronen en benadrukken veelvoorkomende valkuilen.

Bestaanstests

headline = "Where's Waldo?"
print("Waldo" in headline)          # True
print("Wenda" in headline)          # False
print(headline.find("Waldo"))       # 8
print(headline.find("Wenda"))       # -1

Beperkt zoeken met start en end

End is exclusief, dus zoekposities volgen de slice-semantiek.

headline = "Where's Waldo?"
print(headline.find("Waldo", 0, 6))   # -1 (searching "Where'")
print(headline.find("Waldo", 0, 13))  # 8  (searching up to the 'o' in Waldo)

Tellen en vervangen

inventory = "apple, apple, pear, apple"
print(inventory.count("apple"))                # 3
print(inventory.replace("apple", "orange", 2)) # orange, orange, pear, apple

Zoeken en vervangen in Python-strings: oefenvoorbeeld 

Dit voorbeeld verwerkt een lijst met filmbeschrijvingen. Het demonstreert bestaanstests, begrensde zoekopdrachten en veilige vervangingen zonder regex.

blurbs = [
    "Critics say the lead actor delivers a career-best performance.",
    "Fans argue the actor actor scene was intentionally repetitive.",
    "A clever cameo steals the show."
]

for blurb in blurbs:
    # Check whether "actor" appears between indexes 20 and 40 (end exclusive).
    window_has_actor = "actor".casefold() in blurb[20:40].casefold()
    if not window_has_actor:
        print("Window check: actor not found")
        continue

    # If "actor actor" appears, collapse to a single "actor".
    if "actor actor" in blurb:
        print(blurb.replace("actor actor", "actor"))
    # If "actor actor actor" appears, collapse to a single "actor".
    elif "actor actor actor" in blurb:
        print(blurb.replace("actor actor actor", "actor"))
    else:
        print(blurb)

Output:

Window check: actor not found
Fans argue the actor scene was intentionally repetitive.
Window check: actor not found

Conclusie

Gebruik de in-operator voor simpele containments, .find() of .index() wanneer je posities nodig hebt, .count() voor niet-overlappende tellingen en .replace() voor vervangingen. Normaliseer met .casefold() voor case-insensitieve checks, en geef de voorkeur aan speciale prefix/suffix-helpers wanneer dat past. We vermijden het om .find()-resultaten naar Booleans te converteren en behandelen het gedrag van lege substrings als een speciaal geval om stringcode correct en duidelijk te houden.

Onderwerpen

Gerelateerd