Python Beginner Practice & Core Problem Solving
Python idioms, ML evaluation metrics, model serving, and data engineering patterns.
Python idioms, ML evaluation metrics, model serving, and data engineering patterns.
Return the Sum of Two Numbers
A function with no `return` hands back `None`, so a forgotten one surfaces as a `TypeError` at the call site rather than at the line that actually caused it.
Convert Minutes into Seconds
`minutes * 60` returns an `int` when given an `int`, while `/` always produces a float regardless of the operands. Multiplication preserves the type; division does not.
Calculate the Area of a Triangle
`base * height / 2` always yields a float in Python 3 because `/` never returns an int, even for whole numbers. `//` floors instead, which is almost never what an area wants.
Return the Next Number from the Integer Passed
Python integers have no fixed width, so `n + 1` never overflows the way a 32-bit `int` would. The value simply grows to whatever memory allows.
Return the Remainder from Two Numbers
`%` gives the remainder and `//` the floor of the division, and `divmod()` returns both in one call. With negatives the result follows the divisor's sign, so `-7 % 3` is `2`.
Convert Hours and Minutes into Seconds
Unit conversion is one multiply per step: `hours * 3600 + minutes * 60`. Converting each unit separately and adding avoids the rounding drift that chained divisions introduce.
Check if Number is Less Than or Equal to Zero
Python chains comparisons, so `0 <= n <= 10` is one expression and evaluates `n` exactly once. Writing it with `and` gives the same answer but evaluates the middle term twice.
The Farm Problem: Counting Animal Legs
Multiplying each count by its legs and summing is `O(1)` no matter how large the herd, using arithmetic rather than iteration. Looping over individual animals does the same work n times over.
Check if Number is Even or Odd
`n % 2` gives `0` for even and `1` for odd. Python keeps the sign of the divisor, so `-3 % 2` is `1` here where C and JavaScript would return `-1`.
Return the First Element in a List
`lst[0]` raises `IndexError` on an empty list, where `lst[:1]` quietly returns an empty list. Negative indices count from the end, making `lst[-1]` the last element.
Convert String to Integer and Vice Versa
`int("12")` parses, but `int("12.5")` raises `ValueError` rather than truncating. `int(12.5)` does truncate, toward zero, which is why the two look inconsistent.
Get Word Count in a Sentence
`split()` with no argument collapses runs of whitespace and ignores leading and trailing spaces. `split(" ")` does neither, so a double space yields an empty string in the result.
Find the Minimum and Maximum Numbers in a List
`min()` and `max()` each walk the list once, so calling both is two passes over the same data. On an empty list they raise `ValueError` unless a `default=` is supplied.
Check if a String is Empty
An empty string is falsy, so `if not s:` covers it without calling `len()`. That same test also catches `None`, which is usually what you want and occasionally the bug.
Compare Strings by Character Length
`len()` on a `str` counts characters, not bytes, so an accented letter still counts as 1. It is `O(1)` because Python stores the length rather than walking the string.
Concatenate First and Last Name into Full Name
An f-string builds one new string in a single pass, evaluating each expression where it appears. Repeated `+` inside a loop allocates a fresh string on every iteration instead.
Calculate the Factorial of a Positive Integer
Recursion mirrors the mathematical definition but stacks a frame per call, hitting Python's default limit near 1000. `math.factorial()` is iterative in C and has no such ceiling.
Check if a List Includes an Element
`in` scans a list front to back, so membership costs `O(n)`. On a `set` the identical expression becomes a hash lookup at `O(1)`: same syntax, very different work.
Reverse a List in Python
`[::-1]` returns a reversed copy, `.reverse()` mutates in place and returns `None`, and `reversed()` gives a lazy iterator that copies nothing. Three spellings, three different costs.
Filter Out Strings from a List
`isinstance(x, int)` returns `True` for a `bool`, because `bool` subclasses `int` in Python. Filtering for numbers without excluding booleans quietly keeps `True` and `False` in the result.
H4ck3r Sp34k: String Character Replacement
`str.translate()` walks the string once against a lookup table, where chained `.replace()` calls walk it once each. The table also cannot re-replace a character an earlier pass produced.
Count Occurrences of a Character in a String
`str.count()` scans the whole string, so counting one character is `O(n)`. Counting several in a loop repeats that scan each time, where `collections.Counter` walks it once for all of them.
Calculate the Sum of Cubes of a Range
`sum(n**3 for n in range(x))` streams one value at a time, where the bracketed comprehension materialises every cube first. Same answer, `O(1)` memory against `O(n)`.
Check if a Number or String is Symmetrical
`s[::-1]` builds a reversed copy, so comparing it against `s` is a palindrome test in one expression. It costs `O(n)` extra memory that two pointers would avoid.
Check if a Dictionary is Empty
An empty dict is falsy, so `if not d:` is the idiomatic check. `d == {}` is true for it as well, but cannot tell an empty dict from `None`: only `is None` does that.
Repeat an Element N Times in a List
`[x] * n` repeats the reference rather than the object, so `[[]] * 3` produces three names for one list. Mutating one appears to change all three; a comprehension builds distinct objects.
Generate Even Numbers with List Comprehension
`[n for n in range(x) if n % 2 == 0]` materialises the entire list in memory. Swapping the brackets for parentheses gives a generator that produces each value only when asked.
Spelling It Out: Progressive Substring List
`s[:i]` copies the first `i` characters, so building every prefix of a string totals `O(n^2)` work. Fine for a word, worth knowing before it meets a large input.
Extract & Format City Facts from a Dictionary
`d["key"]` raises `KeyError` when the key is absent; `d.get("key")` returns `None` instead. Which you want depends on whether a missing key is a bug or an expected case.
Check if One List can be Nested in Another
One range nests inside another when its `min` is no lower and its `max` no higher. Comparing those two boundaries is a single `O(n)` pass; sorting first is unnecessary.