Python · free · no signup

Learn python, with practice after every lesson

10 lessons, about 151 minutes of reading, and 30 multiple-choice questions. Each lesson names the mistake that most often costs people the interview, because that is where the hours actually go. Part of the free coding course.

Variables and types

Basics Python · 12 min · 10 XP

A variable is a name for a value you want to use again. Python does not ask you to declare the type β€” you assign a value and Python works out what it is. That convenience is why Python is usually the fastest first language for an adult learner, and it is also the first thing that will confuse you when a number arrives from a spreadsheet as text and refuses to add up.

Four types cover almost everything you will do early on: a whole number (int), a decimal (float), text (str), and a true/false value (bool). Knowing which you are holding matters, because Python will refuse to add text to a number rather than guess what you meant. That refusal is a feature. Languages that guess produce the bug where 5 + "3" quietly becomes 53 and nobody notices until a total is wrong.

The habit worth building now is checking rather than assuming. When something behaves strangely β€” a comparison that should be true isn't, a sum that comes out as a long string of digits β€” type(x) tells you what you are actually holding in one line. Most of the confusion in the first fortnight is a str pretending to be an int, and this is how you catch it in seconds instead of an hour.

Syntax

name = "Priya"        # str
age = 29              # int
rate = 1250.50        # float
is_available = True   # bool

print(f"{name} is {age} and charges {rate}/hr")
print(type(age))      # <class 'int'>

Key points

  • Assignment uses a single =, comparison uses ==. Mixing them is the single most common first-week bug.
  • type(x) tells you what you are actually holding when something behaves unexpectedly.
  • f-strings (f"...{value}...") are the modern way to build text; older tutorials use + or %.
The mistake that costs people the interview: Adding a number to text: "Total: " + 5 raises TypeError. Convert first with str(5), or use an f-string.

Practice challenge

Average MarksBasics
Task

Calculate average = (sum of marks) / (number of exams)

Expected output
81.66666666666667
Show a hint
  1. Average = Sum / Count
  2. Add all three marks first
  3. Divide by 3

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does type(29) return?

  1. <class 'str'>
  2. <class 'int'>
  3. <class 'float'>
  4. <class 'bool'>
Show answer

B. <class 'int'>

2. Which line correctly builds a message?

  1. f"Hi {name}"
  2. f"Hi name"
  3. "Hi " + 29
  4. "Hi {name}"
Show answer

A. f"Hi {name}"

3. Which is assignment, not comparison?

  1. age == 29
  2. age = 29
  3. age >= 29
  4. age != 29
Show answer

B. age = 29

Back to the syllabus ↑

Lists and loops

Basics Python · 15 min · 15 XP

A list holds several values in order. Most real work is a loop over a list: every row in a spreadsheet, every file in a folder, every customer in an export. Once you can loop over a list and do something to each item, you can automate most repetitive office work β€” and that is genuinely the point at which people stop describing themselves as learning to code.

Python's for loop reads almost like English: for each item in the list, do this. You rarely need to track an index manually, which is where people coming from other languages over-complicate things. If you find yourself writing for i in range(len(items)) and then using items[i], you are writing C in Python β€” iterate over the items directly and the code gets shorter and harder to get wrong.

The second habit is knowing what already exists. sum(), max(), min() and len() are built in, and a hand-written loop that adds numbers up is one of the clearest signals in a code review that someone is new. Reaching for the built-in is not laziness; it is correctness, because those functions handle the edge cases you have not thought about yet.

Syntax

scores = [82, 45, 91, 67]

total = 0
for s in scores:
    total += s

print("Total:", total)          # 285
print("Average:", total / len(scores))
print("Highest:", max(scores))
print("Passed:", [s for s in scores if s >= 60])

Key points

  • len(list) gives the count; indexes start at 0, so the last item is list[len(list)-1] or simply list[-1].
  • sum(), max(), min() already exist β€” writing a loop for these is a common beginner tell.
  • A list comprehension [x for x in items if condition] filters in one readable line.
The mistake that costs people the interview: Dividing by len(scores) when the list might be empty raises ZeroDivisionError. Check the list is non-empty first.

Practice challenge

Average ValueBasics
Task

Calculate mean = sum / count

Expected output
80.0
Show a hint
  1. sum(marks) / len(marks)
  2. Sum = 400, Count = 5
  3. 400 / 5 = 80

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does scores[-1] give for [82, 45, 91]?

  1. 82
  2. 45
  3. 91
  4. An error
Show answer

C. 91

2. What is the index of the first item in a Python list?

  1. 0
  2. 1
  3. -1
  4. It depends
Show answer

A. 0

3. Which filters a list to values over 60?

  1. [x for x in s if x > 60]
  2. filter(s > 60)
  3. s.filter(60)
  4. for x > 60 in s
Show answer

A. [x for x in s if x > 60]

Back to the syllabus ↑

Functions and reuse

Working level Python · 15 min · 20 XP

A function is a named block of code you can run repeatedly with different inputs. The moment you copy and paste a few lines and change one value, that is the signal to write a function instead. It is not about elegance β€” it is that the copied version now has two places to fix when the logic is wrong, and you will find one of them.

Good functions do one thing and return a value rather than printing it. Returning keeps the function useful in other contexts; printing locks it to the screen and makes it impossible to test. This distinction sounds academic until you try to write your first test and discover that the only way to check your function is to read the output with your own eyes, every time, forever.

Default arguments let one function serve several cases without duplication, and raising an error on impossible input is better than returning a wrong number quietly. A function that accepts a negative salary and returns a negative tax figure has not failed β€” it has produced a plausible answer that will travel a long way through a system before anyone questions it.

Syntax

def take_home(gross, tax_rate=0.2):
    """Return pay after tax. Rate defaults to 20%."""
    if gross < 0:
        raise ValueError("gross cannot be negative")
    return round(gross * (1 - tax_rate), 2)

print(take_home(50000))        # 40000.0
print(take_home(50000, 0.3))   # 35000.0

Key points

  • Default arguments (tax_rate=0.2) let one function serve several cases without duplication.
  • return hands a value back; print only displays it. A function that prints cannot be reused or tested.
  • Raise an error on impossible input rather than silently returning a wrong number.
The mistake that costs people the interview: Using a mutable default like def add(item, items=[]) β€” the list is created once and shared across every call, which produces baffling bugs. Use None and create it inside.

Practice challenge

Bandwidth ThrottlingWorking level
Task

Calculate available bandwidth.

Expected output
25
Show a hint
  1. Subtract current from max
  2. Available = max - current
  3. 100 - 75 = 25

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does take_home(50000) return with the default rate?

  1. 50000
  2. 40000.0
  3. 10000
  4. An error
Show answer

B. 40000.0

2. Why prefer return over print inside a function?

  1. It is faster
  2. The value can be reused and tested
  3. It uses less memory
  4. print is deprecated
Show answer

B. The value can be reused and tested

3. Which default argument is unsafe?

  1. x=0
  2. x=None
  3. x=[]
  4. x=""
Show answer

C. x=[]

Back to the syllabus ↑

Dictionaries and real data

Working level Python · 15 min · 20 XP

A dictionary maps a key to a value β€” a name to a phone number, an ID to a record. Almost all real data arriving from an API or a CSV becomes dictionaries, so this is the structure you will use most in working code, and being fluent with it is a large part of what separates someone who can follow a tutorial from someone who can handle a real file.

Lookup by key is effectively instant regardless of size, which is why a dictionary is the fix when you find yourself scanning a whole list repeatedly to find matching items. If you have a loop inside a loop comparing IDs, you almost certainly want a dictionary β€” the code gets shorter and the runtime drops from minutes to milliseconds on any real volume of data.

The habit that matters in production is never assuming a key exists. Real data has gaps: the customer with no email, the row where the region was left blank, the record that predates a field being added. employee["missing"] raises KeyError and stops the program; employee.get("missing", default) returns a fallback and keeps going. Choosing deliberately between those two is the actual skill.

Syntax

employee = {"name": "Ravi", "dept": "Finance", "years": 6}

print(employee["name"])            # Ravi
print(employee.get("city", "N/A")) # N/A β€” no KeyError

employee["city"] = "Pune"          # add
for key, value in employee.items():
    print(f"{key}: {value}")

Key points

  • employee["missing"] raises KeyError; employee.get("missing", default) returns a fallback instead.
  • .items() gives key and value together β€” the normal way to loop a dictionary.
  • Keys must be unique; assigning an existing key overwrites rather than adding.
The mistake that costs people the interview: Assuming a key exists because it usually does. Real data has gaps β€” use .get() with a default, or check with 'in' first.

Practice challenge

Battery Voltage CheckWorking level
Task

Determine if battery needs charging.

Expected output
False
Show a hint
  1. Compare voltage with minimum
  2. voltage < min means needs charging
  3. 11.2 >= 10.5 so OK

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does employee.get("city", "N/A") return when city is absent?

  1. KeyError
  2. None
  3. "N/A"
  4. ""
Show answer

C. "N/A"

2. Which loops keys and values together?

  1. .items()
  2. .keys()
  3. .values()
  4. .pairs()
Show answer

A. .items()

3. Why use a dict instead of scanning a list repeatedly?

  1. It uses less memory
  2. Lookup by key is far faster
  3. It keeps order
  4. It allows duplicates
Show answer

B. Lookup by key is far faster

Back to the syllabus ↑

Making decisions with if

Basics Python · 12 min · 10 XP

Programs become useful the moment they can choose. An if statement runs a block only when a condition is true; elif checks another condition when the first fails; else catches everything remaining. Almost every piece of business logic you will ever write is a stack of these, describing rules somebody explained to you in a meeting.

Python uses indentation rather than braces to mark which lines belong to the block. This is not decoration β€” the indentation is the syntax, and getting it wrong changes what your program does rather than merely how it looks. A line indented one level too far runs inside the loop instead of after it, which is a bug that reads as correct until you check the output.

Order matters more than beginners expect. The first matching branch wins, so a condition like score >= 60 placed above score >= 80 means nobody ever gets the higher grade β€” the broader rule catches them first. When a set of rules produces one category too often, this ordering is almost always the reason, and it is worth checking before anything else.

Syntax

score = 72

if score >= 80:
    grade = "A"
elif score >= 60:
    grade = "B"
else:
    grade = "C"

print(grade)          # B

# Conditions can combine:
if score >= 60 and score < 80:
    print("Solid pass")

Key points

  • Order matters β€” the first matching branch wins, so put the narrowest condition first.
  • and requires both sides true; or requires either; not flips the result.
  • Comparison returns a real boolean, so `if is_active:` is cleaner than `if is_active == True:`.
The mistake that costs people the interview: Mixing tabs and spaces for indentation. It can look identical on screen and still raise IndentationError β€” pick spaces and let your editor enforce it.

Practice challenge

Boolean ConditionBasics
Task

Print the result of comparing 85 >= 80.

Expected output
True
Show a hint
  1. Use >= for comparison
  2. This creates a boolean value
  3. True or False are the results

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. With score = 72, which branch runs?

  1. A
  2. B
  3. C
  4. None
Show answer

B. B

2. What marks a block in Python?

  1. Braces { }
  2. Indentation
  3. begin/end
  4. Semicolons
Show answer

B. Indentation

3. Which is true only when both sides are true?

  1. or
  2. and
  3. not
  4. xor
Show answer

B. and

Back to the syllabus ↑

Working with text

Basics Python · 14 min · 15 XP

A great deal of office automation is text handling: cleaning a name, splitting a code, checking a file extension, stripping the stray spaces that arrive with every export anyone has ever sent you. Python's string methods cover almost all of it without any external library, which is why a short script can replace an afternoon of manual tidying.

Strings are immutable β€” every method returns a new string rather than changing the original. Beginners lose hours to this, calling s.upper() and wondering why s never changed. The rule is simple once you have been caught by it: if you want to keep the result, assign it back. s = s.upper(), not s.upper() on its own.

The methods worth knowing on day one are .strip() to remove surrounding whitespace, .split(sep) to break text into a list, and the in operator to test for a substring. Between them they handle most of the cleaning that real data needs, and chaining them β€” raw.strip().lower().replace(",", "") β€” reads left to right, each step feeding the next.

Syntax

raw = "  Priya Sharma , Finance "

clean = raw.strip()                 # trim both ends
name, dept = clean.split(",")
print(name.strip().upper())         # PRIYA SHARMA
print(dept.strip().lower())         # finance

print("sharma" in clean.lower())    # True
print(clean.replace(",", " β€”"))

Key points

  • .strip() removes surrounding whitespace; .split(sep) breaks text into a list.
  • in tests for a substring β€” simpler than writing a search loop.
  • Chain carefully: raw.strip().upper() reads left to right, each step feeding the next.
The mistake that costs people the interview: Expecting s.upper() to modify s. It returns a new string; you must assign it back with s = s.upper().

Practice challenge

Branch Name ValidationBasics
Task

Validate branch name format.

Expected output
True
Show a hint
  1. Use .isalnum() or check characters
  2. Valid if only lowercase letters and hyphens
  3. No spaces or uppercase

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does " hi ".strip() return?

  1. " hi "
  2. "hi"
  3. "hi "
  4. An error
Show answer

B. "hi"

2. Does s.upper() change s itself?

  1. Yes
  2. No β€” it returns a new string
  3. Only for ASCII
  4. Only in Python 3
Show answer

B. No β€” it returns a new string

3. How do you test whether text contains "abc"?

  1. "abc" in text
  2. text.has("abc")
  3. text.contains("abc")
  4. in(text,"abc")
Show answer

A. "abc" in text

Back to the syllabus ↑

Errors and files

Working level Python · 16 min · 25 XP

Real input breaks things: the file is missing, the number is text, the network drops halfway through. try/except lets you handle the failure deliberately instead of the program stopping dead with a stack trace that means nothing to the person who ran it. This is the difference between a script you can give someone and one only you can operate.

Catch the specific error you expect. A bare except swallows everything β€” including typos in your own code β€” and turns a five-second fix into an afternoon of confusion, because the program now fails silently in the wrong place with the wrong message. FileNotFoundError and ValueError are specific enough to tell you what actually went wrong.

The other half is closing what you opened. with open(...) closes the file automatically, even when an error is raised inside the block, which matters more than it sounds: files left open lock on Windows, exhaust handles on servers, and produce failures that appear hours later in something unrelated. Use with every time and the problem never exists.

Syntax

def read_total(path):
    try:
        with open(path) as f:
            return sum(float(line) for line in f if line.strip())
    except FileNotFoundError:
        print(f"No file at {path}")
        return 0
    except ValueError:
        print("File contains something that isn't a number")
        return 0

print(read_total("sales.txt"))

Key points

  • with open(...) closes the file automatically, even if an error is raised inside.
  • Catch named exceptions (FileNotFoundError, ValueError) rather than a bare except.
  • Returning a sensible default keeps the caller working; re-raise instead when the caller must know.
The mistake that costs people the interview: Using `except:` on its own. It also catches your own NameError typos and hides the real problem behind a misleading message.

Practice challenge

Break StatementWorking level
Task

Use break to exit loop when found.

Expected output
7
Show a hint
  1. break stops the loop
  2. Use break when condition is met
  3. Only first match will print

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. Why use `with open(...)`?

  1. It is faster
  2. It closes the file automatically
  3. It reads binary
  4. It locks the file
Show answer

B. It closes the file automatically

2. Which error fires when text can't become a number?

  1. TypeError
  2. ValueError
  3. KeyError
  4. IndexError
Show answer

B. ValueError

3. Why avoid a bare `except:`?

  1. It is slower
  2. It hides bugs like typos
  3. It is deprecated
  4. It needs a finally
Show answer

B. It hides bugs like typos

Back to the syllabus ↑

Classes and objects

Advanced Python · 20 min · 30 XP

A class bundles data with the operations on that data. Once a set of functions all take the same dictionary as their first argument, that is the moment a class starts paying for itself β€” you are already passing state around, and a class simply gives that state a name and keeps the functions next to it.

__init__ runs when you create an instance and sets up its attributes. self refers to the instance being worked on; it is passed automatically, which is why you write it in the definition but not at the call site. That asymmetry confuses almost everyone once, and then never again.

The rule that saves real debugging time is where state lives. An attribute defined in the class body rather than inside __init__ is shared by every instance, so one object's change appears on all of them. With a mutable default like a list, this produces bugs that look supernatural β€” an object you just created already has data in it. Put instance state in __init__ and it cannot happen.

Syntax

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def raise_by(self, pct):
        self.salary = round(self.salary * (1 + pct / 100), 2)
        return self.salary

    def __repr__(self):
        return f"Employee({self.name}, {self.salary})"

e = Employee("Ravi", 50000)
e.raise_by(10)
print(e)            # Employee(Ravi, 55000.0)

Key points

  • self is the instance; you declare it but never pass it when calling e.raise_by(10).
  • __init__ is the constructor β€” it sets initial state, it does not return anything.
  • __repr__ gives a readable printout, which makes debugging dramatically easier.
The mistake that costs people the interview: Defining an attribute on the class body instead of inside __init__. A mutable class attribute is shared by every instance, so one object's change appears on all of them.

Practice challenge

Blame Author DetectionAdvanced
Task

Parse blame line to get author name.

Expected output
rajkumar
Show a hint
  1. Author is before first space
  2. Split by space and get first
  3. blame_line.split()[0]

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does __init__ do?

  1. Frees memory
  2. Runs when an instance is created
  3. Imports modules
  4. Returns the class
Show answer

B. Runs when an instance is created

2. Do you pass self when calling e.raise_by(10)?

  1. Yes
  2. No β€” Python passes it automatically
  3. Only for static methods
  4. Only in Python 2
Show answer

B. No β€” Python passes it automatically

3. Why define __repr__?

  1. Speed
  2. A readable printout for debugging
  3. It is required
  4. To enable sorting
Show answer

B. A readable printout for debugging

Back to the syllabus ↑

Comprehensions and clean transforms

Advanced Python · 14 min · 20 XP

A comprehension builds a list, dict or set in one expression instead of a loop with an append. It is not just shorter β€” it states the intent. A reader sees 'this produces a list of X where Y' rather than having to trace what a loop accumulates across four lines and decide whether anything else happens in between.

The rule of thumb interviewers use: a comprehension should read as one thought. If you need two conditions and a nested loop, write the loop. Cleverness that takes thirty seconds to read is a cost, not a skill, and the person paying it is usually you in six months. The filter goes at the end β€” [x for x in items if condition] β€” and an if before the for means something different entirely.

Generator expressions are the same syntax with round brackets, and they do not build the whole list in memory. For a million-row file that distinction is the difference between a script that runs and one that fills the machine's memory and is killed. Use a comprehension when you need the list, a generator when you only need to iterate once.

Syntax

rows = [
    {"name": "Priya", "dept": "data", "salary": 1200000},
    {"name": "Sam",   "dept": "eng",  "salary": 1800000},
    {"name": "Ana",   "dept": "data", "salary": 1500000},
]

# list comprehension with a filter
data_team = [r["name"] for r in rows if r["dept"] == "data"]

# dict comprehension: name -> salary in lakhs
lakhs = {r["name"]: round(r["salary"] / 100000, 1) for r in rows}

# set comprehension: unique departments
depts = {r["dept"] for r in rows}

print(data_team)  # ['Priya', 'Ana']
print(lakhs)      # {'Priya': 12.0, 'Sam': 18.0, 'Ana': 15.0}
print(depts)      # {'data', 'eng'}

Key points

  • The filter goes at the end: [x for x in items if condition]. An if BEFORE the for is a conditional expression and means something different.
  • Dict comprehensions need both a key and a value: {k: v for ...}. Forgetting the colon silently gives you a set instead.
  • A generator expression uses round brackets and does not build the whole list in memory β€” use it when you only need to iterate once over something large.
The mistake that costs people the interview: Building a comprehension purely to avoid a loop, then nesting two of them. If you cannot say what it produces in one sentence, a plain loop is the better answer and every reviewer will agree.

Practice challenge

Class with MethodsAdvanced
Task

Define methods and call them on object.

Expected output
15 5
Show a hint
  1. Methods take self as first parameter
  2. self refers to instance
  3. Call with obj.method(args)

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. What does [n * 2 for n in [1, 2, 3] if n > 1] produce?

  1. [2, 4, 6]
  2. [4, 6]
  3. [2, 4]
  4. [1, 2, 3]
Show answer

B. [4, 6]

2. Which builds a dictionary?

  1. {x for x in items}
  2. [x: y for x in items]
  3. {k: v for k, v in pairs}
  4. (k: v for k in items)
Show answer

C. {k: v for k, v in pairs}

3. When should you write a plain loop instead?

  1. Whenever the list is long
  2. When the comprehension no longer reads as one thought
  3. Never, comprehensions are always better
  4. Only for dictionaries
Show answer

B. When the comprehension no longer reads as one thought

Back to the syllabus ↑

pandas for real analysis

Job-ready Python · 18 min · 25 XP

pandas is what Python analysts actually spend their day in. A DataFrame is a table held in memory: rows, named columns, and an index. Almost every analyst task is filter, group, aggregate, join β€” the same four verbs as SQL, in a different notation, which is why analysts who know SQL pick pandas up in days rather than weeks.

The reason it appears in so many analyst job descriptions is not the syntax. It is that a pandas script is repeatable. A spreadsheet answer has to be redone by hand next month and will differ slightly because somebody dragged a formula one row short; a script runs again and produces the same answer. That is what 'automated the weekly report' means on a resume, and it is the single most common thing analysts are actually hired to do.

The trap that catches everyone once is chained assignment. df[df.x > 1]["y"] = 0 operates on a temporary copy, raises SettingWithCopyWarning, and often changes nothing at all β€” while looking exactly like code that worked. Use .loc[mask, "y"] = 0 instead, which addresses the original frame directly and is unambiguous about what is being modified.

Syntax

import pandas as pd

df = pd.read_csv("applications.csv")

# filter
recent = df[df["applied_on"] >= "2026-01-01"]

# group and aggregate
by_source = (recent
    .groupby("source")
    .agg(applications=("id", "count"),
         interviews=("got_interview", "sum"))
)
by_source["rate"] = (by_source["interviews"] / by_source["applications"] * 100).round(1)

print(by_source.sort_values("rate", ascending=False))
#            applications  interviews  rate
# referral             12           7  58.3
# careers_page         41          9   22.0
# job_board           156         11   7.1

Key points

  • df[mask] filters rows; df[["a", "b"]] selects columns. The doubled brackets trip up everyone once.
  • groupby().agg() with named arguments produces readable column names instead of a confusing multi-level header.
  • Chain operations inside brackets rather than reassigning df at every step β€” it keeps the transformation readable as a sequence.
The mistake that costs people the interview: Modifying a filtered slice and expecting the original to change. df[df.x > 1]["y"] = 0 raises SettingWithCopyWarning and often does nothing. Use .loc[mask, "y"] = 0 instead.

Practice challenge

Correlation DetectionAdvanced
Task

Check if both increase together.

Expected output
True
Show a hint
  1. Check if both lists increase together
  2. all() checks all pairs
  3. Both increase = positive correlation

Open this exercise in the app → · Auto-graded coding rounds

Check yourself

1. Which selects two columns?

  1. df["a", "b"]
  2. df[["a", "b"]]
  3. df.a.b
  4. df("a", "b")
Show answer

B. df[["a", "b"]]

2. Why is a pandas script preferred to a spreadsheet for a recurring report?

  1. It is faster to write once
  2. It repeats identically next month
  3. It uses less memory
  4. It looks more professional
Show answer

B. It repeats identically next month

3. How do you safely set a value on filtered rows?

  1. df[mask]["y"] = 0
  2. df.loc[mask, "y"] = 0
  3. df.set(mask, "y", 0)
  4. df[mask].y = 0
Show answer

B. df.loc[mask, "y"] = 0

Back to the syllabus ↑

Common questions

Do I need any background to start Python?

No. This track begins at its own beginning and assumes nothing, and the first lesson explains what the thing is before showing you any syntax.

How long does the Python track take?

About 151 minutes of reading across 10 lessons, plus the practice challenges and 30 multiple-choice questions, which is where the time actually goes.

Is it free?

Yes, and there is no account. Everything runs in your browser.

More: all 15 tracks · what employers actually ask for · the full syllabus

Keep reading

The STAR method, properly: how to build answers that hold up
A working guide to STAR interview answers: how to weight each part, how to build five stories that cover most…
Returning to work after a career break: rebuilding confidence and explaining the gap
How to present a career break on your CV, close the confidence gap, and answer interview questions about time…
Free AI interview coach
Free AI interview coach: voice mock interviews that talk back, role-specific questions, coding practice and…
Interview countdown, prediction & mock practice
Free interview prep: a live countdown to your interview date, then the 15 most common questions as flip-cards…