Validate Email

A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
medium
Seniority
L3

Problem

Does a string arriving at our signup form look like an email: exactly one '@' with something before it, and a domain after it whose first '.' has at least one character on each side? Return True if so and False otherwise; no other character matters.

Looks like an email. But is it?

Example 1

Input:

email = "analyst@company.com"

Output:

true

Example 2

Input:

email = "bad-email"

Output:

false

Worked solution and explanation

Why this problem exists in real interviews

This is positional parsing dressed up as a membership check. Everyone writes '@' in email and '.' in email; that line accepts 'an.alyst@company', 'chen@@data.com' and 'analyst@.com', because the question was never WHETHER the characters appear but WHERE they sit. The candidates who pass split once, on exactly one '@', and then interrogate only the piece after it.


Break down the requirements

Step 1: Guard on exactly one '@'

Check email.count('@') != 1 first and bail out. Only then is local, domain = email.split('@') guaranteed to unpack into two pieces; skip the count and 'chen@@data.com' raises a ValueError instead of returning False.

Step 2: Reject an empty part before the '@'

Return early when local is empty. This is the one rule the domain check cannot cover for you: '@company.com' has a perfectly valid domain, so without this guard it sails through.

Step 3: Let the first dot decide the domain

domain.partition('.') splits on the first dot and hands back an empty tail when there is no dot at all. So 'analyst@company', 'analyst@.com', 'analyst@company.' and an empty domain all fail one check: bool(head) and bool(tail).


The solution

Boolean rules without a regex
def is_valid_email(email: str) -> bool:
    if email.count('@') != 1:
        return False
    local, domain = email.split('@')
    if not local:
        return False
    head, _, tail = domain.partition('.')
    return bool(head) and bool(tail)

Common follow-up questions