C.W.K.
Stream
Lesson 07 of 12 · published

Named Groups — (?P<name>...)

~8 min · named-groups, readability

Level 0Pattern-Curious
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

Numbered groups are fragile, named groups are stable

When your pattern grows, group numbers shift every time you add or remove parens. Named groups solve this by giving each capture a name you reference instead of a number.

Syntax varies by flavor:

  • Python / older PCRE: (?P<name>...)
  • .NET / PCRE / JavaScript: (?<name>...)
  • Backreference to named group (Python): (?P=name)
  • Backreference to named group (.NET / PCRE): \k<name>

Python supports BOTH the (?P<name>...) form (its own) AND (?<name>...) as of 3.x. Cross-language, prefer the bare angle-bracket form when possible.

Why use named groups

Three reasons:

  1. Readable callers. m.group('year') is self-documenting; m.group(1) requires comments.
  2. Stable across edits. Adding a group in the middle doesn't break m.group('year').
  3. Self-documenting patterns. Future-you reads (?P<email>...) and knows what's being captured.

The cost

None worth mentioning. Named groups are free. Use them whenever a group's purpose isn't obvious from position.

Code

Named groups·python
import re

# Python style
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
m = re.match(pattern, '2026-05-04')
print(m.group('year'))   # '2026'
print(m.group('month'))  # '05'
print(m.groupdict())     # {'year': '2026', 'month': '05', 'day': '04'}

# Cross-flavor angle bracket form (also works in Python 3.x)
pattern = r'(?<year>\d{4})-(?<month>\d{2})'

# Backreference by name
re.findall(r'(?P<word>\w+)\s+(?P=word)', 'the the cat sat sat')
# ['the', 'sat']

# Self-documenting validators
USER = re.compile(r'''
    ^
    (?P<localpart>[\w.+-]+)
    @
    (?P<domain>[\w-]+\.[\w.-]+)
    $
''', re.VERBOSE)
m = USER.match('hi@pippa.dev')
print(m.group('localpart'))  # 'hi'
print(m.group('domain'))     # 'pippa.dev'

External links

Exercise

Take any 2-3 group pattern you've written and rewrite it with named groups. The matching code that uses it should now be self-documenting (e.g., m.group('year') instead of m.group(1)).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.