practicepython.in
python exercises
171 exercises

Practice Python where the feedback
explains itself.

Most practice sites tell you that a test failed. This one tells you what your code did — that it returned None because the function fell off the end, that it quietly emptied the list it was handed, that the values are right but you built tuples where lists were asked for. No account, nothing to install. Python runs in your browser.

practicepython.in assumes you can already write a small function — def, return, an if. Brand new to Python? Start at pythonmastery.io and come back when that feels easy.

171 exercises17 tracksPython 3.13Runs offline after first load
Daily puzzle One short Python puzzle a day. What does it print? Play today’s →

New here

Three gentle ones to start with. Nothing is locked: the editor and the Check button work on every exercise, in any order, and the hints cost nothing.

Keep a number inside a range min and max, guard clauses ~10 min Initials from a name str.split, join ~10 min Read a yes or no from text truthiness versus meaning, sets for membership ~12 min What percentage is this of that true division, guarding the divisor ~10 min One file, two files f-strings, optional parameters ~10 min Convert without crashing try / except, naming the exception ~10 min File sizes people can read f-string format specs, loops with early return ~15 min 1st, 2nd, 3rd, 11th modulo, special case before general rule ~15 min Round to the nearest step banker’s rounding, floor division tricks ~15 min Capitalise a title properly why str.title() is wrong, word-level rules ~15 min
The last few, and the zero that is not zero negative slicing, the -0 trap ~12 min Chunk a sequence slicing, range with a step ~15 min Remove duplicates, keep the order sets for membership, the seen pattern ~15 min Flatten one level of nesting nested comprehensions, reading order ~15 min Rotate a list without falling over modulo for wrapping, slice and rejoin ~15 min The total so far, at every step carrying state through a loop, accidentally quadratic ~15 min One cut, two pieces, nothing lost complementary slices, slices clamp ~15 min Taking turns until everyone is done *args, round-robin ~20 min The longest stretch of the same thing consecutive grouping, best-so-far ~20 min Page through a list 1-based vs 0-based, slicing ~20 min Rows become columns zip(*rows), unpacking into a call ~18 min Sliding windows over a sequence overlapping slices, the range bound ~20 min
Show only the last four string repetition, negative slicing ~12 min camelCase to snake_case re.sub with backreferences, two passes ~20 min Titles into URL slugs regular expressions, re.sub ~15 min Back the other way, without flattening the capitals capitalize() lowercases the rest, leading underscores ~16 min Shorten text without cutting a word in half rsplit, slicing ~15 min The words people actually used tokenising, Counter ~18 min Finding the addresses in a wall of text findall, greedy boundaries ~22 min Marking the words somebody searched for re.escape, alternation order ~22 min Parse a key=value string str.split with maxsplit, skipping empties ~20 min Getting the text out of the markup greedy versus lazy matching, entity decoding order ~22 min Breaking a paragraph into lines greedy algorithms, accumulating a buffer ~22 min The comma that is not a separator character scanning, state machines ~28 min
Tally records by a field dict.get with a default, accumulating ~15 min Index records by a unique field dict as an index, detecting duplicates ~15 min Pull one field out of every record comprehension over records, a default that means absent ~12 min New names, same places rebuilding a dict, keeping order ~16 min The best few, without disturbing the rest sort stability, reverse= versus reversing ~18 min Reach into nested data safely walking nested dicts, defaults over exceptions ~20 min Group records by a field dict.setdefault, grouping ~20 min Turning a lookup around the inverse of a function, silent collisions ~20 min Sorting by several fields at once stable sort, successive passes ~24 min What changed between these two set algebra on keys, three-part results ~25 min Nested data, one level deep recursion over a tree, path building ~25 min Merge configuration, deeply recursion, deep vs shallow copy ~30 min
Days between two dates date.fromisoformat, timedelta ~15 min Cents into something readable divmod on negatives, format specs ~15 min Read 1h30m as seconds finditer, consuming the whole string ~25 min Three minutes ago ladder of thresholds, rounding a duration ~24 min Split money without losing a cent integer cents, divmod ~20 min Add months to a date calendar arithmetic, divmod for wrapping ~30 min Counting the days that count weekday(), inclusive ranges ~26 min Collapsing the bookings that touch sort then sweep, comparing against the last kept item ~26 min
Transform every value in a mapping functions as arguments, dict comprehensions ~15 min Sorting when some of the keys are missing decorate-sort-undecorate, None does not compare ~18 min Chain two functions into one returning a function, closures ~20 min A decorator that keeps a tally attributes on a function, functools.wraps ~22 min Find the first one that fits next with a default, generator expressions ~20 min Run it the first time and never again state that outlives a call, None is a real result ~20 min Both halves, one pass higher-order functions, calling a predicate once ~20 min Remember what you already worked out decorators, closures over a cache ~28 min Steps in the order you read them returning a function, left to right ~24 min Retry something that fails sometimes functions as arguments, try/except in a loop ~25 min
The class you barely have to write @dataclass, generated __eq__ and __repr__ ~18 min A Stack that knows how long it is __len__ and free truthiness, private attributes ~20 min Settings nobody can change behind your back frozen dataclass, hashable values ~22 min Keys that do not care about capitals __getitem__ and friends, normalising at the boundary ~24 min Stock that cannot go negative methods that guard state, zero is not a stock level ~24 min A Money value that behaves like one __eq__ and NotImplemented, __add__ ~25 min A Temperature that cannot be impossible @property, computed attributes ~25 min An object you can loop over twice __iter__, iterable versus iterator ~24 min A set that keeps the order you added things operator dunders, returning new objects ~28 min Versions that sort like versions tuple comparison, functools.total_ordering ~30 min
Swap a file’s extension pathlib without touching disk, with_suffix ~15 min Three fields and everything else maxsplit, fixed fields plus a free-text tail ~18 min Directory, name, stem, suffix rpartition, the last dot, not the first ~18 min The last few lines splitlines, negative slicing ~15 min Turn CSV rows into records zip, header rows ~20 min The metadata block at the top of the file a fence is only a fence in the right place, returning a pair ~22 min Make two JSON payloads comparable json.loads and dumps, objects unordered, arrays ordered ~20 min Sections, settings and the lines that are neither line-oriented parsing, state across lines ~24 min Back out to rows and columns a header is a decision, missing versus empty ~20 min A file too big to hold iterables you can only read once, single pass ~26 min
Comparing floats without lying float equality, relative versus absolute tolerance ~15 min An error message somebody can act on what a message must contain, !r for ambiguous values ~18 min Report every missing field at once collecting errors, present but falsy ~15 min Everything arrives as a string converting at the boundary, bool('False') is True ~24 min One shape in, one shape out accepting more than one shape, one cleaning path ~20 min Rules as functions, errors as data rules you can pass around, collecting every failure ~24 min Code that asks for the time instead of taking it injecting the clock, reading a value once ~25 min A block of code that has to leave something alone context managers, post-conditions ~26 min
The last batch is smaller generators, the ragged final batch ~18 min Four numbers that describe a classifier true and false, positive and negative, counting in one pass ~18 min The average, and the other average mean versus median, the even-length middle ~18 min Squeezing a column into nought and one rescaling, the zero-range column ~18 min Ninety-nine per cent accurate and completely uselessdebug accuracy on rare events, the majority-class baseline ~20 min Perfect in validation, useless in productiondebug data leakage, fit on train, apply to test ~24 min Categories a model can actually add up categories are not numbers, a fixed vocabulary ~24 min Two numbers that disagree, and the one that combines them precision versus recall, undefined metrics ~24 min Holding some data back shuffling with a seed, reproducibility ~24 min Dividing by n, or by n minus one Bessel’s correction, sample versus population ~22 min How unusual is this number standardising, units of standard deviation ~20 min The same patient on both sides of the splitdebug group leakage, the unit of independence ~26 min Every row gets a turn at being the test set cross-validation, distributing a remainder ~26 min Turning scores into probabilities without overflowing numerical stability, exp overflow ~26 min
Selecting with a condition instead of a loop boolean arrays, & rather than and ~20 min Running totals and the gaps between readings cumsum, diff shortens the array ~20 min An if statement with no if in it np.where, both branches are evaluated ~20 min Where the largest value is, not what it is argmax returns a position, unravel_index ~24 min A slice of an array is not a copy of it views versus copies, assigning into a slice ~22 min Shapes that stretch to fit broadcasting rules, trailing dimensions ~24 min Brightening a pixel until it goes dark fixed-width integers, silent wraparound ~24 min Picking rows in an order you choose indexing with an array, fancy indexing copies ~22 min The value that is not equal to itself nan propagation, isnan rather than == ~24 min The same numbers, a different shape reshape, the -1 dimension ~20 min Three lists into three columns stack adds a dimension, concatenate joins one ~22 min The at sign is not the star @ versus *, inner dimensions must match ~26 min
How the answers split, as a percentage value_counts, normalize for proportions ~20 min The update that quietly did nothingdebug chained assignment, copy versus view ~24 min Half the league scored nothingdebug Series arithmetic aligns on the index, NaN from a missing label ~24 min The region that vanished from the reportdebug groupby drops missing keys, dropna=False ~24 min The total came out as a sentencedebug object dtype is not a number, to_numeric with errors='coerce' ~26 min The latest status, out of an event log drop_duplicates with subset and keep, sort before you dedupe ~26 min One row per channel, and a cost per click groupby with named aggregations, reset_index turns keys back into a column ~26 min A row-by-row loop over a table whole-column arithmetic, np.where and Series.clip ~26 min The month we sold everything twicedebug many-to-many merges, validate= ~26 min The grid averaged what it should have addeddebug pivot_table defaults to mean, pivot raises where pivot_table averages ~30 min Every month, including the quiet ones to_datetime and the .dt accessor, grouping by a period ~30 min The best three in every region groupby().head() takes the first rows, not the best, sort by several keys with one call ~28 min
The basket that adds up to almost rightdebug float equality, tolerance ~20 min The leaderboard where 9 beats 100debug sort keys, strings that look like numbers ~20 min 'int' object is not callabledebug shadowing a built-in, name lookup order ~18 min The basket that remembersdebug default arguments, when defaults are evaluated ~20 min The snippet that is short at one end and wrong at the otherdebug exclusive slice ends, negative indices wrap ~22 min The cleanup that crashes halfway throughdebug mutating while iterating, build rather than delete ~20 min The filter that misses every other onedebug iterating while modifying, how for walks a list ~20 min Three discount buttons, one discountdebug closures, late binding ~25 min
The stock count that tried to count the word quantitydebug reading a ValueError, the quoted value ~15 min The chart that crashes on the last daydebug reading an IndexError, the last iteration ~15 min The total that crashes on a price without a pound signdebug reading a traceback, a function that falls off the end ~15 min The podium that sorted into nothingdebug reading a NoneType error, methods that return None ~15 min The setting that is there and cannot be founddebug reading a KeyError, repr of a key ~15 min The digit sum that never reaches zerodebug reading a RecursionError, a base case that is never reached ~20 min The class list that will not sortdebug errors raised inside a built-in, None in data ~20 min The balance that exists and cannot be readdebug reading an UnboundLocalError, scope ~20 min
The flag that should be any() any and all, short-circuiting ~15 min The string built one piece at a time str.join, immutable strings ~15 min The if-chain that should be data dict as a lookup table, data versus control flow ~15 min The counter that enumerate already keeps enumerate with start, manual counters ~15 min Unwinding the arrow guard clauses, early return ~20 min Numbers that do not say what they are named constants, one definition per rule ~18 min The three lines that are one line setdefault, defaultdict ~18 min The lookup that scans everything dict as an index, nested loops ~20 min
Brackets that close in the right order a list as a stack, matching pairs ~20 min The best day to buy and the best day to sell running minimum, one pass ~20 min The first letter that appears only once count first, then look, Counter ~15 min The one ticket number nobody handed in the sum you expect, arithmetic instead of searching ~15 min Two numbers that add up to a target dict as a lookup, one pass ~20 min The best run of consecutive days Kadane’s algorithm, extend or start again ~25 min The longest stretch with no letter repeated sliding window, last seen position ~30 min Merge the meetings that overlap sort first, compare with the last kept ~25 min
Flatten a list of lists of lists recursion, base case ~20 min Add up numbers hidden at any depth recursion, base case ~15 min How deep does it go? recursion, max of the answers ~15 min Every way to choose from a list recursion that branches, building new lists ~25 min Every order the letters can go in permutations, recursion that branches ~25 min Find it in a sorted list by halving binary search, recursion on a range ~25 min How much space is this folder using? recursion over a tree, two kinds of node ~20 min Move the tower, one disc at a time recursion with two calls, trusting the smaller call ~25 min Sort a list by splitting it in half divide and conquer, merging two sorted lists ~30 min