Loading...
Loading...
Python interview guide
Classes, inheritance, dunder methods, properties and dataclasses. Every answer is short enough to say aloud, and every question links to the lesson that teaches it.
49 questionsLast updated
Keep the balance in a private attribute with no public setter. Expose it through a read-only property, and change it only in methods such as deposit and withdraw that validate first and then update. Tests then cover both the error and the unchanged state.
Lesson: Encapsulation Checkpoint and Interactive LabThe caller receives a reference to the same list, so it can append, remove or clear entries and bypass every rule the class enforces. Returning a tuple or a copy gives a safe view, at the cost of a small copy.
Lesson: Encapsulation Checkpoint and Interactive LabIt is a class method, such as from_dict or from_line, that builds an instance from a different kind of input. Python has one __init__, so named class methods keep each way of building an object readable and keep parsing and validation inside the class instead of in every caller.
Lesson: @classmethod and Alternative Constructorscls is the class the method was called on. If a subclass inherits the factory, cls(...) builds the subclass, while a hard-coded name would always return the parent type and quietly break polymorphism.
Lesson: @classmethod and Alternative ConstructorsIt forces the caller to have an object before one can be created. The method does not use self, so it should be a class method (called as Order.from_json(text)) so it can run without an instance.
Lesson: @classmethod and Alternative ConstructorsThe right side reads the inherited count, the assignment creates a new count attribute on the subclass, and the parent keeps its old value. If every class must share one counter, assign through the parent explicitly (Base.count += 1).
Lesson: @classmethod and Alternative ConstructorsValidate inside the class method before calling cls(...): check the parts, convert types, and raise ValueError with a clear message. Better still, let __init__ or property setters hold the rules so every route into the class is checked.
Lesson: @classmethod and Alternative ConstructorsYes. Python binds a class method to type(instance), so cls is still the class. This is why instance.from_text(...) works, though calling it on the class reads clearer.
Lesson: @classmethod and Alternative ConstructorsWhen the helper is closely tied to the class, only that class uses it, and readers would look for it there, such as Order.is_valid_code. If it is general or shared by several classes, a plain module function is simpler and needs no class name.
Lesson: @staticmethod and When a Plain Function Is BetterA class with no state and only static methods is acting as a module. Python already has modules for grouping functions, so the class adds noise and the habit usually comes from languages where every function must be inside a class.
Lesson: @staticmethod and When a Plain Function Is BetterTypeError saying the function takes N positional arguments but N+1 were given, because Python passes the instance as the first argument. Called on the class it still works, which can hide the mistake until an instance call.
Lesson: @staticmethod and When a Plain Function Is BetterIt receives neither self nor cls, so it cannot discover which subclass called it. A class method receives cls and can read cls.RATE, which is why rate-like data should be reached through a class method.
Lesson: @staticmethod and When a Plain Function Is BetterThey are pure functions of their arguments, so a test calls them with plain values and checks the result, with no object to build and no hidden state to set up.
Lesson: @staticmethod and When a Plain Function Is BetterUse an instance method if it needs one object's data, a class method if it builds objects or uses class-level data, and a static method only when it needs neither and belongs with the class. Otherwise use a function in the module.
Lesson: @staticmethod and When a Plain Function Is BetterWhether the class holds any state. If not, it is a bag of functions and should be a module. If methods share data, convert them to instance methods and pass the data through self.
Lesson: Class and Static Methods CheckpointKeep one validating __init__, and add two class methods, from_code and from_dict, that parse their input and return cls(...). A static is_valid_plan helper is shared by __init__. All routes then enforce the same rules and subclasses keep their own type.
Lesson: Class and Static Methods CheckpointIt ignores the class it was called on, so TeamSubscription.from_code(...) still returns a Subscription. Using cls(...) keeps the subclass type and avoids rewriting the factory in each subclass.
Lesson: Class and Static Methods CheckpointIf the helper is part of the class's idea and others will look for it there, make it static. If it is general, or used by unrelated classes, keep it a module function. In both cases it needs neither self nor cls.
Lesson: Class and Static Methods CheckpointLSP (the "L" in SOLID) asserts that objects of a superclass should be replaceable with objects of a subclass without breaking application correctness. A violation occurs if a subclass changes parameter signatures, narrows return types unexpectedly, or raises unexpected exceptions not declared by the parent contract.
Lesson: Single Inheritance and Method OverridingInheritance creates tight coupling between base and child classes; modifying a base class can silently break subclasses (fragile base class problem). Composition ("has-a") models relationships by embedding component objects, allowing dynamic swapping of behaviors at runtime and greater testability.
Lesson: Single Inheritance and Method OverridingNo. Python only supports public inheritance. All accessible attributes and methods of a parent class are inherited by subclasses.
Lesson: Single Inheritance and Method OverridingIt checks the instance __dict__, then the class, then each parent class in the Method Resolution Order. The first match wins. This is why a child's method hides a parent's method of the same name.
isinstance(True, int) true, and why does it matter?bool is a subclass of int, so True is an int with value 1. It is a good reminder that isinstance follows inheritance, and that checking for int can accept booleans you did not intend.
Not at runtime. Python trusts the programmer. You can mark a method with typing.final so type checkers and linters complain, and you can document the rule, but the interpreter will not enforce it.
self.helper() and the child overrides helper(). Which one runs for a child object?The child's. self is the child object, so lookup starts at the child. This lets a parent define a fixed algorithm while children customise one step. It also means a parent must not assume its own helper is the one that runs.
The Diamond Problem arises when classes B and C both inherit from A, and class D inherits from both B and C (D(B, C)). In languages with naive depth-first lookup, A’s methods would be visited twice or resolved inconsistently. Python solves this using C3 Linearization, which guarantees that subclasses appear before parents and the relative order of parents is preserved, resulting in [D, B, C, A, object] where A is visited exactly once.
Yes. If inheritance declarations create contradictory order requirements (for example, class X(A, B) and class Y(B, A) followed by class Z(X, Y)), Python detects that no consistent linear order exists and raises TypeError: Cannot create a consistent method resolution order (MRO) at class definition time.
When called inside a method with zero arguments super(), Python compiler automatically fills in the current class and instance (super(__class__, self)). You can also pass explicit arguments, such as super(BaseClass, self) to begin MRO traversal at a specific ancestor in the chain.
super() always mean "my direct parent"?No. It means the next class after the current one in the MRO of the object. In single inheritance that is the parent. In a diamond, super() inside B can reach C, a sibling, because C comes next in the object's MRO.
A child always comes before its parents, the left-to-right order of the parents in the class line is kept, and the order is consistent for every subclass. If those rules cannot all be met, Python raises a TypeError when the class is defined.
Lesson: The super() Proxy and Method Resolution Order (MRO)The chain stops there. Classes later in the MRO never run for that method. This is why every class that takes part in cooperative multiple inheritance must call super() and pass on arguments it does not use.
Keep it small, give it one capability, avoid its own __init__ state if possible, and make it depend only on a simple contract such as an attribute or method the host class provides. Put mixins before the main base class in the class line so their methods are found first.
Duck typing in Python is completely dynamic and resolved at runtime: Python attempts method dispatch when the instruction executes, raising an AttributeError if absent. Structural typing in TypeScript or Go is checked statically at compile-time: compiler verifies that types have matching shape before allowing the program to compile.
LBYL is preferred when the check has no race condition and handling an exception is significantly more expensive than the check (for example, in high-frequency loops where an exception would generate expensive tracebacks), or when distinguishing between an attribute missing on the target object versus an attribute error raised internally inside the method.
Lesson: Polymorphism and Duck Typingtyping.Protocol introduces static duck typing into Python. Classes do not need to inherit from the Protocol, but static type checkers (like mypy or pyright) can verify at compile time that an object implements all methods and signatures declared in the Protocol.
Mistakes show up only when the line runs, and the expected interface is not written anywhere. Teams add type hints with Protocol, unit tests that cover each implementation, and clear names and docstrings. An ABC is an option when a hard check at instantiation is worth the extra structure.
try/except AttributeError risky?An AttributeError raised by a bug deep inside the method is caught the same way as a missing method, so the real defect is hidden. Look the method up first with getattr, or keep the try block around only the call you expect to fail.
With inheritance, objects share a parent that declares the method and isinstance can confirm it. With duck typing, objects only share a method name and behaviour, with no common class. Python supports both; duck typing needs less code and ties classes together less.
Any object with read() works where a file is expected, any iterable works in a for loop, and any object with __enter__ and __exit__ works in a with statement. The built-ins ask for the protocol, not for a class.
An ABC uses runtime inheritance (class Concrete(AbstractBase)) and enforces method presence at object instantiation time via ABCMeta. A Protocol (PEP 544) uses structural subtyping: classes never need to inherit from the Protocol, and compliance is verified statically by tools like mypy without runtime instantiation checks.
ABC is simply a convenience class whose metaclass is ABCMeta. ABCMeta overrides the __call__ method when allocating objects: it inspects the class’s __abstractmethods__ attribute (populated by @abstractmethod) and raises a TypeError if any abstract methods remain un-overridden.
collections.abc provides abstract base classes like Iterable, Sequence, Mapping, and MutableMapping. Inheriting from MutableMapping and implementing only minimal core methods (__getitem__, __setitem__, __delitem__, __iter__, __len__) gives your class free concrete implementations of get(), keys(), values(), items(), clear(), update(), and pop().
@abstractmethod instead of raising NotImplementedError in the base method?The abstract method fails when the object is created, so an incomplete subclass cannot even start. NotImplementedError fails only when that method is eventually called, which might be deep into a running program or never be tested.
@abstractmethod actually check?Only that a concrete subclass overrides each abstract name before an object is created. It does not compare parameters, return types or behaviour. It also needs ABCMeta, which you get by inheriting from ABC.
register() better than inheritance?When you cannot change the class, such as one from a third-party library, but you want isinstance checks against your ABC to accept it. Registered classes are not checked for the abstract methods, so they should be tested on their own.
collections.abc.Mapping instead of dict?The ABC accepts any mapping-like object, such as OrderedDict, MappingProxyType or your own class, not just dict. Your function stays open to more inputs while still giving a clear check.
Is-a means the child is a more specific kind of the parent and can replace it everywhere, so you use inheritance. Has-a means one object contains another as a part, so you store it in an attribute. Ask which sentence sounds right: "A Manager is an Employee" or "A Customer has an Address".
Lesson: Has-a versus Is-a: Why Prefer CompositionInheritance couples the child to every detail of the parent and is fixed when the class is written. Composition keeps the parts behind small interfaces, so you can swap, test and change them independently. It does not ban inheritance; it asks you to justify it.
Lesson: Has-a versus Is-a: Why Prefer CompositionThe subclass inherits every public method, so callers can use insert, pop(0) or update and break the rules of your class. Built-in methods may also skip your overridden methods. Holding the list or dict in a private attribute gives you full control.
Lesson: Has-a versus Is-a: Why Prefer CompositionEach lesson has quizzes, practice and more interview questions on the same topic.
Open the first lesson