Capturing Groups and Named Groups
Parentheses for capture, (?P ...) named groups, re.fullmatch(), lookahead/lookbehind.
Capturing Groups and Named Groups is a free Learn AI with Python lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Learn AI with Python learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Groups?
Groups let you isolate parts of a match so you can extract exactly the piece you want — the area code from a phone number, the year from a date, the username from an email.
This lesson covers capturing, named, non-capturing groups, and lookarounds.
Capturing Groups with ( )
Wrap part of a pattern in parentheses to capture it. The whole match plus each group becomes accessible on the Match object.
import re
m = re.search("(\d{4})-(\d{2})-(\d{2})", "Date: 2026-05-29")
print(m.group()) # "2026-05-29" (whole match)
print(m.group(1)) # "2026"
print(m.group(2)) # "05"match.group, groups, groupdict
Useful accessors:
m.group(0)— entire matchm.group(n)— the nth capturem.groups()— a tuple of all captures
import re
m = re.search("(\d{4})-(\d{2})-(\d{2})", "2026-05-29")
print(m.groups()) # ("2026", "05", "29")
year, month, day = m.groups()Named Groups with (?P<name>...)
Numbering groups gets fragile. Named groups use (?P<name>...) so you reference captures by a meaningful name.
import re
m = re.search("(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2026-05-29")
print(m.group("year")) # "2026"
print(m.group("month")) # "05"groupdict for Structured Output
m.groupdict() returns all named groups as a dictionary — perfect for turning matched text into structured records.
import re
m = re.search("(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2026-05-29")
print(m.groupdict())
# {"year": "2026", "month": "05", "day": "29"}Non-Capturing Groups (?:...)
Sometimes you need parentheses only for grouping (e.g. to apply a quantifier) but do NOT want a capture. Use (?:...).
This keeps your group numbering clean.
import re
# Group "ab" so + applies, but do not capture it
m = re.search("(?:ab)+(\d+)", "ababab42")
print(m.group(1)) # "42" -> group 1 is the digits, not "ab"Backreferences
A backreference \1 matches the same text a group captured earlier. Useful for finding repeated words.
import re
# Find a word repeated twice in a row
print(re.findall("(\w+) \1", "the the cat cat sat"))
# ["the", "cat"]Lookahead (?=...)
A positive lookahead (?=...) asserts what must follow, without consuming it. The asserted text is not part of the match.
Here we match a number only if it is followed by "px".
import re
print(re.findall("\d+(?=px)", "10px 20em 30px"))
# ["10", "30"] -> "20" skipped (not followed by px)Negative Lookahead (?!...)
A negative lookahead (?!...) asserts what must NOT follow. Match the number only if NOT followed by "px".
import re
print(re.findall("\d+(?!px)", "10px 20em 30px"))
# matches numbers not followed directly by pxLookbehind (?<=...) and (?<!...)
Lookbehind asserts what comes before the match without consuming it:
(?<=...)positive — must be preceded by(?<!...)negative — must NOT be preceded by
Here we grab amounts preceded by a dollar sign, without capturing the sign.
import re
print(re.findall("(?<=\$)\d+", "price $50 and 60 units"))
# ["50"] -> only the amount after $Combining Groups and Lookarounds
Real extractors mix these tools. This pattern pulls a named price that must be preceded by a currency symbol and followed by a decimal part:
import re
text = "Total: $1299.99 paid"
m = re.search("(?<=\$)(?P<amount>\d+)\.(?P<cents>\d{2})", text)
print(m.group("amount"), m.group("cents")) # 1299 99Quick Check: Named Groups
You want to extract matches by a readable name like "year" instead of a number.
Recap: Groups and Lookarounds
You can now extract precise structure from text:
( )capturing groups withm.group(n)andm.groups()(?P<name>...)named groups withm.groupdict()(?:...)non-capturing groups for clean grouping- Backreferences
\1for repeats - Lookahead
(?=)/(?!)and lookbehind(?<=)/(?<!)
Next: putting it all together to clean text for AI.
Frequently asked questions
Is the “Capturing Groups and Named Groups” lesson free?
Yes — the full text of “Capturing Groups and Named Groups” is free to read here on the web, and the Learn AI with Python course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Learn AI with Python course, upgrade to CoddyKit PRO.
What will I learn in “Capturing Groups and Named Groups”?
Parentheses for capture, (?P ...) named groups, re.fullmatch(), lookahead/lookbehind. You practise Learn AI with Python with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Learn AI with Python?
No prior experience is required. Learn AI with Python on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Capturing Groups and Named Groups” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Learn AI with Python lesson?
Yes. Every Learn AI with Python lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Regex Patterns and Character Classes
- re Module: search, match, findall, sub
- Capturing Groups and Named Groups
- Text Cleaning for AI with Regex