Data Validation with Regular Expressions
Parentheses in regular expressions mark the portion of a match that findall() should extract and return.
Matching Versus Keeping
A regular expression can recognize more text than you ultimately want to keep. Parentheses solve this problem by marking the specific portion of a successful match that findall() should extract and return. The surrounding pattern still has to match, but the returned result can be only the text inside the parentheses.
Parentheses do not change which text the pattern matches. They change which part of that match findall() returns.
Tracing findall() Results
What do you think happens?
A pattern matches the text X-:42. If the number is enclosed in parentheses, what will findall() return?
Reveal answer
Only the text 42
The full pattern must match, but the parentheses identify 42 as the portion to extract. The extracted result is still a string.
Without parentheses, findall() returns the entire substring that matches the pattern. With one capturing group, findall() returns a list containing the strings captured by that group. Therefore, two patterns can match the same text while producing different findall() results.
Parentheses as Capture Boundaries
A capturing group is the part of a regular expression enclosed in parentheses. Text outside the group remains important because it must match for the overall pattern to succeed. However, findall() returns only the text represented by the group. The location of the parentheses in the pattern therefore determines which portion is extracted.
Extracting a Number From a Marked Line
Consider a line with the form X-:42 and a pattern whose number portion is enclosed in parentheses. What does findall() return?
- 1Match the required structure
The line must contain the expected X- prefix, colon, and number. The pattern outside the parentheses participates in this match.
- 2Identify the captured portion
The parentheses surround the number, so the number is the portion selected for extraction.
- 3Read the findall() result
Because there is one capturing group,
findall()returns a list of strings containing the captured number rather than the complete line.
The result contains the extracted number as a string, not as an integer.
Multiple Captured Values
A pattern can contain more than one set of parentheses. In that case, findall() returns a list of tuples. Each tuple contains the captured values in the order in which the groups appear in the pattern.
Keeping Two Parts of One Match
Suppose a line contains two portions that a pattern captures with two sets of parentheses. What shape should you expect from findall()?
- 1Match the complete line structure
All required text, including the parts outside the parentheses, must match for the pattern to succeed.
- 2Collect the first group
The first parenthesized portion becomes the first value in the result tuple.
- 3Collect the second group
The second parenthesized portion becomes the second value in the same result tuple.
findall() returns a list of tuples, with captured values ordered by their groups in the pattern.
| Pattern structure | findall() result shape | Returned content |
|---|---|---|
| No capturing group | List | Entire matched substrings |
| One capturing group | List of strings | Only the captured substrings |
| Multiple capturing groups | List of tuples | Captured substrings in group order |
The number of capturing groups changes both the content and structure of findall() results.
Converting Extracted Values
Every value extracted by findall() is a string, even when the characters look like a number. If later work requires arithmetic or comparisons using numeric values, convert the extracted strings explicitly to an appropriate type such as int or float.
| Extracted content | Initial result type | Possible later type |
|---|---|---|
| 42 | String | Integer |
| 3.5 | String | Float |
The extracted text begins as a string and may need conversion before numeric use.
Safe Result Handling
Common mistake Treating the full match as the extracted value
What it looks likeExpecting findall() to return X-:42 when the number is enclosed in parentheses
Why it failsWith a capturing group,
findall()returns only the portion inside the parentheses.Do this insteadIdentify which part of the pattern is enclosed in parentheses and use that as the expected extracted result.
Common mistake Assuming an extracted number already has numeric type
What it looks likeUsing a captured value as though it were already an integer or float
Why it failsfindall()always returns extracted values as strings.Do this insteadConvert the string explicitly when arithmetic or numeric comparison is needed.
Common mistake Accessing a result before checking whether a match occurred
What it looks likeReading an element from the result when the input line does not match the pattern
Why it failsFor a nonmatching line,
findall()returns an empty list.Do this insteadVerify that the returned list is non-empty before accessing one of its elements.
Common mistake Expecting the same result shape for every number of groups
What it looks likeTreating results from multiple capturing groups as a simple list of strings
Why it failsWith multiple groups,
findall()returns a list of tuples.Do this insteadUse the number of capturing groups to predict the structure of the result.
When an input line does not match the pattern, findall() returns an empty list. A condition that checks whether the list contains at least one result prevents the program from trying to access a value that is not present.
Practice and Review
For each situation, predict the result shape before writing any processing logic: a pattern with no parentheses, a pattern with one capturing group around the number, and a pattern with two capturing groups. Then decide which extracted values would need conversion before numeric use.
Hints
- Ask whether
findall()should return the complete match or only a captured portion. - Count the sets of parentheses in the pattern.
- Remember that extracted values begin as strings.
- Consider what happens if no input text matches.
- 1Parentheses define capturing groups in a regular expression. The complete pattern still controls whether a line matches, but
findall()returns only the text inside the groups. One group produces a list of strings, while multiple groups produce a list of tuples. Extracted values are strings and may require conversion to int or float. When a line does not match,findall()returns an empty list, so check the result before accessing an element.
Key Takeaways
- A regular expression can match a complete structure while a capturing group selects only the portion to extract.
findall()returns full matches without capturing groups and captured substrings when groups are present.- One capturing group produces a list of strings; multiple groups produce a list of tuples.
- Extracted values are always strings and must be converted when another type is needed.
- Check for a non-empty result before accessing extracted values.