Loading...
Loading...
Python interview guide
Syntax, data types, control flow, functions, strings and error handling. Every answer is short enough to say aloud, and every question links to the lesson that teaches it.
60 questionsLast updated
isdigit() return for an empty string?They return False, because there must be at least one character. This differs from "" in s and s.startswith(""), which are always True. Always check for empty input separately if it matters.
str.splitlines() and str.split('\n')?str.split('\n') only splits on the specific ASCII newline character \n. str.splitlines() recognizes all universal line break standards across platforms (including Windows \r\n, Unix \n, old Mac \r, and Unicode line separators).
split() return when the delimiter is not in the string?A list with the whole string as its only item, for example "abc".split(",") is ["abc"]. It never raises an error, so the result always has at least one item.
Split, reverse the list with a slice, and join: " ".join(sentence.split()[::-1]). Using split() with no argument also removes extra spaces.
Maintain two indices (left at 0, right at len-1). In a while loop (left < right), increment left while not s[left].isalnum() and decrement right while not s[right].isalnum(). If s[left].lower() != s[right].lower(), return False. Advance both pointers. If the loop completes, return True. This uses O(1) space.
Count how often each character appears, then scan from the left and return the first one with a count of 1. With str.count this is O(n²); with a dictionary of counts it becomes O(n).
CPython uses an open-addressing hash table with quadratic probing (perturbation algorithm). In Python 3.6+, dictionaries use a compact memory layout: a sparse array of hash table indices pointing to a dense array containing (hash, key, value). This reduced dictionary memory consumption by 20-25% and introduced guaranteed insertion order preservation.
d.pop(key) and del d[key]?Both remove the key from the dictionary. del d[key] returns nothing (None), while d.pop(key, default) returns the value that was removed (or returns a fallback default if the key does not exist).
A list search checks items one by one, so it takes O(N) time. A dictionary turns the key into a hash number and jumps straight to the slot where the value is kept, so a lookup takes O(1) time on average, however many entries there are.
Lesson: Dictionaries: Key-Value Mappingdict.update() and the | merge operator?d1.update(d2) modifies d1 in place and returns None. The union operator d1 | d2 leaves both d1 and d2 untouched, creating and returning a brand-new merged dictionary.
A dictionary itself has no sort, but sorted(d.items(), key=lambda pair: pair[1]) returns a list of pairs ordered by value. Wrap it in dict(...) to get a dictionary back in that order, because dictionaries keep insertion order.
No. It is a shallow merge: if both dictionaries have the key "db", the whole right-hand value replaces the left-hand one, even when both values are dictionaries. A deep merge needs a small recursive function.
Lesson: Dictionary Methods and Comprehensionsfrozenset in Python?A frozenset is an immutable version of a Python set. Because it is immutable, it is hashable and can be used as a dictionary key or as an element inside another set.
Python adds a random seed to string hashes in every run, for security. A set stores items by their hash, so the internal order changes between runs. A set has no order you can rely on, so use sorted(s) whenever the order matters.
|, &) and set methods (.union(), .intersection())?Set operators require both operands to be actual set instances (e.g. s | [1, 2] raises a TypeError). Set methods accept any arbitrary iterable on the right side (e.g. s.union([1, 2]) automatically converts the list), providing greater flexibility.
A & B for sets of sizes M and N?The time complexity is O(min(len(A), len(B))). Python iterates over the smaller set and performs O(1) hash lookups into the larger set.
Lesson: Mathematical Set OperationsYes. d.keys() and d.items() behave like sets, so d1.keys() & d2.keys() gives the keys both dictionaries share, and d1.keys() - d2.keys() gives the keys only in d1. d.values() does not support this, because values may repeat or be unhashable.
The worst-case time complexity is O(N). This occurs during severe hash collisions, where many distinct keys generate the exact same hash code modulo table size, causing long probing chains. However, Python uses SipHash with randomized secret keys per process to prevent collision attacks.
Lesson: Dictionaries and Sets CheckpointCounter is a dict subclass designed for counting hashable objects. Accessing a missing key in a Counter returns 0 instead of raising a KeyError. It also provides methods like .most_common(k) and multiset mathematical operations.
Use the length as the key and a list as the value: groups.setdefault(len(word), []).append(word) inside a loop. The setdefault call creates the list the first time a length appears. collections.defaultdict(list) does the same job with less code.
BaseException and Exception in Python?BaseException is the root class of the entire exception hierarchy. It has four direct subclasses: Exception (base for all application and standard errors), KeyboardInterrupt (Ctrl+C), SystemExit (sys.exit), and GeneratorExit. Application code should always catch Exception, never BaseException, so that Ctrl+C interrupts and script exits are not unintentionally swallowed.
In modern Python (Python 3.11+ zero-cost exception handling), try blocks have near-zero performance overhead when no exception is thrown. Cost is incurred only when an exception is actively raised and the stack unwinds. Therefore, using try-except for rare exceptional conditions is fast.
TypeError means the object is the wrong type for the operation, such as "5" + 5. ValueError means the type is right but the value is not acceptable, such as int("abc"). Pick the one that matches the problem when you raise your own errors.
Because Python checks except clauses sequentially, placing a general superclass handler (like except Exception:) before a specific subclass (like except ValueError:) will cause the general handler to intercept the exception first, rendering the specific handler unreachable dead code.
When an exception is raised inside an except block, Python automatically attaches the original exception to the __context__ attribute of the new exception (raise NewError from original_error), preserving the full diagnostic root-cause chain in tracebacks.
A long try block can catch an error from a line you did not expect, and then the except message points to the wrong cause. Put only the risky lines in try and the rest in else or after the statement.
try block and the finally block execute a return statement?If the finally block executes a return statement, its return value will overwrite and discard any return value or pending unhandled exception from the try block. For this reason, placing return statements inside a finally block is considered an anti-pattern.
finally block mask an exception from the try block?Yes. If an exception occurs in try, and another exception occurs while executing finally, Python 3 chains them (During handling of the above exception, another exception occurred), but the exception originating from finally is the one that propagates outward.
Without else you would set something like ok = True at the end of try and check it afterwards. else expresses the same idea directly, runs only when try had no error, and keeps errors from the follow-up code from being caught by the except above.
raise ... from ...?Introduced in PEP 3134, raise NewException(...) from original_exception sets the __cause__ attribute, explicitly linking high-level domain exceptions to low-level technical root causes while preserving the original traceback.
raise and raise err inside an except block?A bare raise re-raises the current exception with its original traceback, which is what you almost always want. raise err also works but adds the current line to the traceback, which can confuse the reader. Use bare raise to pass the error on unchanged.
Failing fast means checking inputs at the start of a function and raising an exception at once if they are invalid. The error then appears near its cause, with a clear message, instead of producing wrong results later and being hard to trace.
Lesson: Raising Exceptions and Custom Errorslogging.exception() and logging.error()?logging.exception() logs an error message with severity level ERROR and automatically attaches the current execution traceback (exc_info=True). It should only be called from inside an except handler.
Handle an error where you know how to recover, such as retrying, using a default or skipping a bad record. If the current function cannot fix the problem, let it propagate so a caller with more context can decide. Never swallow an error just to make the traceback disappear.
Lesson: Exception Handling CheckpointA module is a single .py file that holds functions, classes and values. You use it in another file with import. Modules let you reuse code and keep programs organised.
import numpy as np style aliases?An alias shortens a long module name, and many communities use the same nickname, so code is easy to read across projects. Only the alias is created; the original name is not.
Lesson: Importing from the Standard LibraryPython runs the module's code only the first time, then stores the loaded module in sys.modules. Later imports reuse that stored module, so the second import costs almost nothing.
if __name__ == "__main__": do?It runs a block only when the file is started directly, such as python tool.py. When another file imports it, __name__ is the module name and the block is skipped. It keeps demo code out of imports.
random.py?Your script's folder is searched before the standard library, so import random would load your file instead. Code that expected the real module then fails in confusing ways.
Both are .py files. A script is a file you run directly. A module is a file you import. One file can be both, and the main guard is how it tells the two cases apart.
A module is one .py file. A package is a folder of modules, usually with an __init__.py file. You reach a module inside a package with dots, such as shop.pricing.
Each project can need different versions of the same package. A virtual environment keeps one project's packages separate, so installing in one project cannot break another.
Lesson: Packages and pipNo. A package runs code on your machine. Install only well-known packages, check the name for spelling mistakes, and prefer ones with clear documentation and active maintenance.
Lesson: Packages and pipimport report.Python looks for report in the script's folder, then the standard library, then installed packages. At the first match it runs the file once, stores it in sys.modules, and binds the name report. With no match it raises ModuleNotFoundError.
Put the logic in functions and call the entry function under if __name__ == "__main__":. Run directly, the guard is true and the code runs. When imported, the guard is false.
Run python -m pip freeze > requirements.txt inside the project's virtual environment and share the file. Others run python -m pip install -r requirements.txt to get the same set.
with open(...) instead of calling close() yourself?The with statement closes the file even when an error is raised inside the block. A manual close() is skipped if an exception happens before it, which can leave the file open and lose buffered data.
encoding="utf-8"?The default encoding depends on the operating system, so the same file can read differently on two computers. Naming UTF-8 gives one clear rule for every language and every machine.
Lesson: Reading and Writing Text Files\n?The newline is part of the stored text, and Python keeps it. Remove it with strip() or rstrip("\n"), or use split(), which drops it along with other white space.
Path.read_text() and open().read()?They return the same text. read_text() opens, reads and closes the file in one call, which is short for small files. open() inside with gives more control, such as reading line by line.
mkdir(exist_ok=True) do?It creates the folder, and if the folder already exists it does nothing instead of raising FileExistsError. That makes the call safe to repeat.
glob?The order in which files come from the disk depends on the system and is not promised. Sorting gives one order everywhere, so output and tests are repeatable.
Lesson: Paths with pathlib and Missing FilesA CSV file stores only text, so the reader returns strings. Convert with int() or float() before calculating. Skipping this either raises a TypeError or joins text instead of adding.
newline=""?The csv module manages line endings itself. Without newline="", Python may translate them again, which on some systems adds blank rows or breaks newlines inside quoted values.
json.dump and json.dumps?dumps returns the JSON as a string. dump writes it into an open file object. The same pattern holds for loads (from a string) and load (from a file).
dict becomes an object, list and tuple become an array, str stays a string, int and float become numbers, True and False become true and false, and None becomes null. Sets and custom classes need conversion first.
Wrap json.loads in try and catch json.JSONDecodeError (or ValueError). Then show a clear message or use a default. Never trust text from outside to be valid.
"w".Python creates the file if it is missing, or empties it if it exists, and then writes from the start. That is why "a" is the safe choice when you want to keep old content.
Open it with with, call json.load, and catch FileNotFoundError and json.JSONDecodeError. For each case return a default or show a clear message, so the program does not crash.
pathlib for file paths?A Path joins parts with /, picks the right separator for the system and offers exists(), read_text(), write_text(), mkdir() and glob(). It avoids fragile string joins.
Each lesson has quizzes, practice and more interview questions on the same topic.
Open the first lesson