Experienced interview questions
Auto-configuration inspects the classpath and existing beans, then conditionally configures beans using @Conditional annotations. It is driven by entries in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.
At startup, Spring Boot scans the classpath to see which libraries are present and looks at the beans that already exist in the application context. It then evaluates a large set of configuration classes, each guarded by conditional annotations such as @ConditionalOnClass, which only activates if a particular library is on the classpath, and @ConditionalOnMissingBean, which only activates if no matching bean has already been defined.
This design means auto-configuration is additive and overridable rather than fixed. Adding the H2 database dependency, for instance, is enough to switch on an in-memory database connection automatically, because the conditional checks pass once that library appears. Defining a DataSource bean explicitly makes the conditional configuration back off and use that one instead. Understanding this pattern helps when debugging unexpected behaviour, since it can usually be traced back to a condition either matching or failing to match.
The Global Interpreter Lock is a mutex inside the standard CPython interpreter that allows only one thread to execute Python bytecode at any given moment, even on a machine with multiple cores. This means pure Python threads do not give a genuine speedup for CPU-heavy work, since they still take turns rather than truly running in parallel, though threads remain effective for I O bound work where a thread spends most of its time waiting rather than computing.
A closure is a function that remembers and can still access the variables from the scope in which it was created, even after that outer function has finished running. Closures are what make patterns like private variables and function factories possible in JavaScript, since the inner function keeps a live reference to its outer variables rather than a copy of their values at creation time.
A virtual function is a member function in a base class that a derived class is allowed to override with its own version, and the correct version to run is decided at runtime based on the actual type of the object being used, rather than the type of the pointer or reference pointing at it. This enables polymorphism, letting a single piece of code that works with a base class pointer correctly call the most specific overridden behaviour for whatever derived object it actually happens to be holding.
The standard approach is a single class annotated with @RestControllerAdvice that contains one or more methods annotated with @ExceptionHandler, each mapped to a specific exception type. When any controller in the application throws a matching exception, Spring routes it to the appropriate handler method instead of letting the default error page or a raw stack trace reach the caller.
Centralising error handling this way keeps individual controllers focused purely on their main job, since they no longer need repeated try-catch blocks scattered everywhere. It also guarantees every error response has the same shape, typically a small JSON object with a message and an appropriate HTTP status code, which makes life much easier for whoever is consuming the API, whether that is a front-end team or an external partner, because they can write one consistent way of handling failures instead of guessing at each endpoint.
Multiprocessing is the better choice for CPU-bound work, since each process gets its own Python interpreter and memory space, sidestepping the GIL entirely and allowing genuine parallel execution across multiple cores. Threading remains a better fit for I O bound work, such as waiting on network calls or file access, where the overhead of starting a whole new process for each task would outweigh any benefit, and sharing memory between threads is simpler than coordinating separate processes.
The event loop is the mechanism that lets JavaScript, despite running on a single thread, handle asynchronous work without blocking. Synchronous code runs first on the call stack; once the stack is empty, the event loop pulls queued callbacks, such as a finished timer or a completed network request, and pushes them onto the stack to run, which is why asynchronous code always runs after the current synchronous code finishes, no matter how short its delay.
A vtable, short for virtual table, is a hidden table of function pointers that the compiler generates for any class containing virtual functions, with each entry pointing to the correct implementation for that class. Every object of such a class secretly carries a pointer to its class's vtable, and calling a virtual function actually means looking up the right implementation through that table at runtime. This lookup is what makes runtime polymorphism possible, at the cost of a small amount of extra memory and an indirect function call.
Checked exceptions, such as IOException, must either be declared in the throws clause of a method or caught in a try-catch block, and the compiler enforces this at compile time. They generally represent conditions a caller could reasonably be expected to recover from, such as a missing file or a failed network call. Unchecked exceptions extend RuntimeException, are not enforced by the compiler, and typically signal programming mistakes, like dereferencing a null reference or passing an invalid argument.
In practice, many experienced Java developers lean toward unchecked exceptions for their own application errors, reserving checked exceptions for genuinely recoverable situations, because forcing every caller up the chain to declare or catch an exception it cannot meaningfully act on tends to clutter code with boilerplate rather than improve reliability. Spring itself follows this philosophy, favouring unchecked exceptions throughout its own APIs.
A decorator is a function that takes another function as input and returns a new function that usually wraps the original with extra behaviour, such as logging, timing or checking permissions before the original code runs. The at-sign syntax placed above a function definition is simply shorthand for passing that function into the decorator and reassigning the result back to the same name, which is why decorators can transparently add behaviour without changing the decorated function's own code.
The call stack tracks the functions currently being executed, following a last-in-first-out order as functions call other functions. The task queue holds callbacks that are ready to run once the call stack is completely empty, such as a setTimeout callback or a resolved promise handler. The event loop constantly checks whether the stack is empty and, if so, moves the next item from the queue onto it.
A pure virtual function is a virtual function declared in a base class with no implementation at all, marked in a way that forces every concrete derived class to supply its own version before it can be used. A class containing at least one pure virtual function becomes an abstract class, meaning it can never be instantiated directly and exists purely to define a shared interface that derived classes are required to implement, guaranteeing a consistent set of behaviours across all of them.
The first step is finding the actual slow query rather than guessing, usually by enabling SQL logging or a profiler and looking for a pattern where loading a list triggers one extra query per item, known as the N plus one problem. Fixing that specific issue with a fetch join or an entity graph, so related data loads in a single query instead of many, often produces the single largest improvement.
Beyond that one fix, a few standard techniques usually round out the effort: add a database index on columns filtered or sorted on often, since without one the database scans every row; use a projection to select only the fields the screen actually needs instead of loading whole entities; and always page large result sets with a size limit rather than loading everything into memory at once. Applied together, these changes typically turn a query that takes seconds into one that takes milliseconds.
A generator is a special kind of function that produces a sequence of values lazily, one at a time, instead of computing and returning them all at once. Each time yield is reached, the function's state is paused and the yielded value is handed back to the caller, resuming exactly where it left off the next time a value is requested. This makes generators extremely memory efficient for large or even infinite sequences, since only one value needs to exist in memory at a time.
Microtasks, which include promise callbacks and queueMicrotask, are given higher priority and always run to completion before the event loop moves on to the next macrotask. Macrotasks include things like setTimeout callbacks, user interface events and I/O. In practice this means a resolved promise's handler runs before a setTimeout scheduled with a zero-millisecond delay, even though both appear to be waiting for the same moment.
The diamond problem occurs when a class inherits from two separate base classes that both themselves inherit from a single common ancestor, meaning the final derived class ends up with two separate copies of that ancestor's data, one through each inheritance path. This creates real ambiguity: referring to a member from the shared ancestor becomes unclear about which of the two copies is actually meant, and the compiler will typically refuse to compile such an ambiguous reference until it is resolved.
Dependency injection means a class receives the objects it depends on from the outside, usually through its constructor, rather than creating those objects itself with the new keyword. In a Spring application, the framework builds these dependency objects, called beans, once and hands them to whichever class asks for them, wiring the whole application together automatically based on the types involved.
The practical benefit shows up most clearly in testing: because a class accepts its dependencies as constructor parameters, a test can pass in a fake or mock version instead of the real one, allowing the class to be tested in isolation without a real database or network call. It also makes the codebase easier to change over time, since swapping one implementation for another, say switching from one payment provider to another, means changing what gets injected rather than editing every class that uses it.
A function returning a list computes every value up front and holds the entire result in memory before handing it back, while a generator produces each value only when asked, keeping memory use low regardless of how many values there ultimately are. The trade-off is that a generator can only be iterated through once from start to finish, whereas a list can be looped over repeatedly or accessed by index at any time.
A promise is an object representing a value that is not available yet but will be at some point, either successfully or with an error. It can be in one of three states: pending, fulfilled or rejected. Once a promise settles, its result is delivered to functions registered with .then for success or .catch for failure, and this settled state and value are cached, so attaching a handler later still receives the correct result.
Declaring the inheritance from the common ancestor as virtual tells the compiler that, no matter how many separate paths lead back to that same ancestor, only a single shared copy of it should ever exist in the final derived object. This removes the ambiguity entirely, since there is now exactly one copy of the shared base class's data rather than several competing ones. It does add some additional complexity and a small runtime cost, so it is typically reached for only when this specific inheritance shape is genuinely unavoidable.
Rather than piling custom CSS rules on top of Bootstrap and fighting its defaults with increasingly specific selectors, the cleaner approach is to work with the Sass source files Bootstrap itself provides and change the variables they expose, such as colours, spacing scale, border radius and breakpoints, before compiling a custom build of the framework. This way customisation lives in one small, organised place instead of scattered override rules.
This approach also survives upgrades far better. Overriding compiled CSS directly means an update to Bootstrap can easily reorder or rename classes in a way that silently breaks those overrides. Changing the source variables instead means customisations flow through the same build process Bootstrap itself uses, so the framework and the design stay consistent as it evolves, with the added benefit of a smaller final CSS file since only the pieces actually used get compiled in.
A context manager defines what should happen when entering and leaving a with block, using __enter__ to run setup code and __exit__ to run cleanup code, guaranteeing the cleanup runs even if an exception occurs inside the block. This pattern is how files close themselves automatically and how locks release themselves reliably, and a custom class can support the same behaviour simply by implementing those two methods itself.
Both accomplish the same underlying behavior, since async/await is essentially a more readable way to work with promises. Chaining .then calls can become difficult to read once there are several sequential steps or nested conditions, sometimes called callback pyramid problems. async/await lets that same logic be written in a linear, top-to-bottom style that closely resembles synchronous code, with errors handled using an ordinary try/catch block instead of a .catch call.
RAII stands for resource acquisition is initialization, a pattern where acquiring a resource, such as memory, a file handle, or a lock, happens inside a constructor, and releasing it happens automatically inside the matching destructor. Because destructors in C++ run reliably and automatically whenever an object goes out of scope, wrapping any resource this way guarantees it gets cleaned up correctly, even if an exception is thrown partway through, without the programmer needing to remember a manual cleanup step at every possible exit point.
The stack holds each method call as a frame containing its local variables and parameters, and it is strictly short-lived: as soon as a method returns, its frame and everything in it disappears. The heap, in contrast, holds actual objects, and those objects live for as long as something still references them; once nothing points to an object any more, the garbage collector eventually reclaims that memory.
A useful way to picture this is that a local variable on the stack can hold a reference, essentially an address, pointing to an object that physically lives on the heap. So when the line Car myCar = new Car() runs, the reference myCar sits on the stack for the lifetime of that method, while the actual Car object it points to sits on the heap and can keep living even after the method that created it returns, as long as something else still references it, for example if it was returned or stored in a list.
A metaclass is the class of a class, controlling how classes themselves are constructed, in the same way an ordinary class controls how its objects are constructed. Most Python code never needs to touch metaclasses directly, since the default one handles everything transparently, but frameworks sometimes use a custom metaclass to automatically register subclasses, validate class definitions, or inject behaviour into every class built from it.
Every JavaScript object has an internal link to another object, called its prototype, from which it can inherit properties and methods. When a property is accessed on an object and not found directly on it, JavaScript automatically looks up the prototype chain, checking the prototype, then that prototype's own prototype, and so on, until the property is found or the chain ends at null.
A smart pointer is an object that wraps around a raw pointer and automatically manages the lifetime of whatever it points to, releasing that memory once it is no longer needed, following the same RAII idea used for other resources. Unlike a raw pointer, which requires the programmer to remember exactly when and how to release memory manually, a smart pointer handles that bookkeeping on its own, dramatically reducing the chance of memory leaks or accidentally using memory that has already been freed.
A descriptor is an object that customises what happens when an attribute is accessed, assigned or deleted on another class, by implementing special methods such as get, set or delete. The built-in property decorator is actually implemented using descriptors behind the scenes, and writing a custom descriptor is useful when the same attribute-access behaviour, such as validation or lazy computation, needs to be reused across several different classes.
Classical inheritance, found in languages like Java, defines fixed classes at compile time, and objects are instances of those classes. Prototypal inheritance, JavaScript's native model, has objects inherit directly from other live objects through the prototype chain, with no separate blueprint required. JavaScript's class syntax is popular sugar written on top of this same prototypal system rather than a truly separate inheritance model.
A unique ownership smart pointer guarantees that only one such pointer can ever own a given piece of memory at a time, and ownership can be transferred but never duplicated, which keeps its overhead extremely low. A shared ownership smart pointer instead allows several pointers to jointly own the same memory, internally tracking how many owners currently exist and only releasing the memory once the very last owner disappears. Shared ownership is more flexible but carries a small additional cost from that internal reference counting.
A closure is a function that remembers and can still access variables from the scope it was originally defined in, even after that outer scope has already finished running. This happens naturally whenever a function is defined inside another function and returned or passed elsewhere, and it is the underlying mechanism that makes many decorator patterns and callback-based code work correctly without needing to pass extra state around explicitly.
this refers to the object a function is currently executing as a method of, and its value is determined by how the function is called, not where it is defined. Calling obj.method() sets this to obj, calling a function on its own sets this to undefined in strict mode or the global object otherwise, and arrow functions ignore all of this, instead inheriting this from their surrounding lexical scope.
A weak ownership smart pointer refers to memory managed by a shared ownership smart pointer without itself counting as an owner, meaning it does not keep that memory alive on its own. It is primarily used to break a reference cycle, a situation where two shared owners point at each other and would otherwise keep each other alive forever, and to safely check whether the memory they refer to still exists before attempting to use it, without ever forcing that memory to stay alive artificially.
Method resolution order, often shortened to MRO, is the specific sequence Python follows when searching through a class and all of its parent classes to find which version of a method or attribute to actually use. With multiple inheritance, more than one parent might define the same method, so Python uses a consistent algorithm, called C3 linearization, to decide a predictable order rather than leaving it ambiguous, and this order can be inspected directly on any class.
call and apply both invoke a function immediately with a specified this value, differing only in how additional arguments are passed: call takes them individually while apply takes them as a single array. bind does not invoke the function immediately; instead it returns a brand new function permanently bound to the given this value, useful when a function needs to be passed around and called later with the correct context.
Move semantics allow the resources owned by a temporary or otherwise disposable object, such as memory it has allocated internally, to be transferred directly into a new object instead of being fully copied and then discarded. Rather than duplicating potentially large amounts of data, ownership of the underlying resource is simply handed over, leaving the original object in a valid but essentially empty state. This can dramatically improve performance for operations that would otherwise involve expensive, unnecessary copying of large objects.
asyncio achieves concurrency within a single thread by having functions voluntarily pause at await points, letting the event loop run other pending work while one task is waiting on something like a network response. Threads instead achieve concurrency by letting the operating system switch between multiple threads of execution. asyncio avoids the overhead and complexity of thread synchronization, but it only helps for I O bound work and requires the whole call chain to be written in a compatible, cooperative style.
The temporal dead zone is the period between when a let or const variable enters scope, due to hoisting, and when its declaration line actually executes. Trying to access the variable during this window throws a ReferenceError rather than returning undefined, which is a deliberate safety improvement over how var silently allows access before its declaration.
An rvalue reference is a reference type specifically designed to bind to temporary values that are about to be destroyed anyway, rather than to a normal, named, long lived variable. It is what makes move semantics possible, since a function can detect through an rvalue reference parameter that the object it received is temporary and safe to plunder for its resources, rather than needing to make a full, expensive copy of something that was going to disappear immediately afterward regardless.
Concurrency means multiple tasks are making progress over the same period of time, potentially by interleaving on a single core, while parallelism means multiple tasks are genuinely executing at the exact same instant on separate cores. Python threads and asyncio both provide concurrency without true parallelism for CPU-bound work because of the GIL, while multiprocessing achieves real parallelism by using entirely separate processes and interpreters.
Currying is transforming a function that takes multiple arguments into a sequence of functions that each take a single argument, one at a time, with each call returning a new function until all arguments have been supplied. It is often used to create specialized, reusable versions of a more general function by pre-filling some of its arguments in advance.
The rule of three states that if a class needs to explicitly define any one of a custom destructor, a custom copy constructor, or a custom copy assignment operator, it almost certainly needs to define all three of them. This is because needing one of these usually signals the class is managing some resource, like raw memory, whose default copying behaviour, a simple bit for bit copy, would be incorrect and could cause serious problems for the other two operations as well.
Default argument values are evaluated only once, at the moment the function is defined, not each time the function is called, so a mutable default such as an empty list is actually the same shared object reused across every call that does not explicitly supply its own. Any modification made to it during one call quietly persists and shows up unexpectedly the next time the function is called. The standard fix is to default the argument to None and create a fresh mutable object inside the function body instead.
A higher-order function is a function that either accepts another function as an argument, returns a function as its result, or both. Array methods like map, filter and reduce are common examples, since each takes a callback function as an argument, and this pattern is central to functional programming style in JavaScript.
The rule of five extends the older rule of three to also include the move constructor and the move assignment operator, both introduced when move semantics were added to the language. If a class manages a resource and needs custom copy behaviour, it typically also benefits from custom move behaviour for efficiency, so all five special member functions, the destructor, copy constructor, copy assignment, move constructor, and move assignment, are usually considered together as a complete, consistent set.
A circular import happens when two modules end up importing each other, either directly or indirectly through a longer chain, so that loading one requires the other to already be fully loaded, which it is not yet. Common fixes include moving the import statement inside the function that actually needs it rather than at the top of the file, restructuring the code so shared logic lives in a third module both can depend on, or combining the two modules if they are tightly coupled enough to belong together anyway.
Debouncing delays running a function until a certain amount of time has passed without the triggering event happening again, resetting the timer every time the event fires in the meantime. It is commonly applied to a search input, so a network request only fires once the user has actually paused typing, rather than on every single keystroke.
The rule of zero suggests that, whenever possible, a class should avoid managing raw resources directly at all, and should instead compose itself out of existing types, such as smart pointers and standard containers, that already correctly handle their own construction, destruction, copying, and moving. Following this approach, a class needs to define none of the five special member functions itself, since the compiler generated defaults will correctly forward all of that responsibility to the well behaved member objects it is built from.
A memory leak in Python usually comes from objects that remain unintentionally reachable, such as a growing global list or cache that nothing ever clears, references held in closures or callbacks that outlive their intended purpose, or circular references between objects that override the del method in a way that prevents the cycle-detecting collector from cleaning them up. The garbage collector reclaims memory for genuinely unreachable objects, but it cannot help with memory that a program is still technically holding onto by mistake.
Throttling ensures a function runs at most once within a given time interval, no matter how many times the triggering event fires during that interval. It is commonly used on scroll or resize event handlers, which can fire dozens of times per second, to limit expensive work like layout recalculations to a manageable, steady rate.
Template specialization lets a programmer provide a separate, customized implementation of a template for one particular type or set of types, instead of relying on the single generic version that would otherwise be generated for every type. This is useful when the generic implementation would be technically correct but inefficient or awkward for a specific type, letting that one case be handled with genuinely tailored logic while every other type continues to use the ordinary, general purpose version of the template.
Python primarily relies on reference counting, immediately freeing an object the moment its reference count drops to zero, meaning nothing in the program can reach it any more. This alone cannot handle groups of objects that reference each other in a cycle but are otherwise unreachable from the rest of the program, so a separate cyclic garbage collector periodically scans for and cleans up exactly these reference cycles that plain reference counting would otherwise miss entirely.
Common causes include forgotten timers or intervals that are never cleared, event listeners attached to elements that are removed from the page without being detached first, and references to objects held inside a global variable or a growing cache that is never cleaned up. Since the garbage collector only frees memory for objects with no remaining references, anything still referenced, even accidentally, stays in memory indefinitely.
A function template defines a single generic function whose parameter and return types are filled in automatically by the compiler based on whatever arguments are actually passed when it is called. A class template instead defines an entire generic class, and the specific type it should work with generally has to be stated explicitly when an object of that class is created. The well known vector container is itself a class template, since it can hold integers, strings, or objects of any other type depending on how it is declared.
A weak reference lets one object refer to another without increasing its reference count, meaning the referenced object can still be garbage collected normally even while the weak reference to it exists. This is useful for building caches or observer-style relationships where you want to keep track of an object without being the reason it stays alive in memory longer than it otherwise would.
JavaScript uses automatic garbage collection, most commonly based on an algorithm called mark-and-sweep. The collector periodically starts from a set of root references, such as global variables and currently executing functions, and marks every object reachable from them; anything left unmarked, meaning nothing in the program can reach it anymore, is considered garbage and its memory is reclaimed.
The Standard Template Library is a large collection of ready made, generic containers, iterators, and algorithms that ship as part of the C++ standard library. Containers such as vector and map store and organise data, iterators provide a uniform way to step through the contents of any container, and algorithms such as sort or find operate generically on any container through those same iterators. Together these three pieces let common data handling tasks be written once and reused across essentially any type of data.
__slots__ declares a fixed set of attribute names a class is allowed to have, which stops Python from creating the usual per-instance dictionary that normally stores an object's attributes. This noticeably reduces memory usage for classes that create a very large number of instances, since each object skips the overhead of that dictionary, though it comes at the cost of no longer being able to freely add new attributes that were not declared up front.
CommonJS, the module system originally used by Node.js, uses require to import and module.exports to export, and it loads modules synchronously. ES modules, the standard built into the language itself, use import and export keywords, support static analysis so tools can determine dependencies without running the code, and load asynchronously, which is better suited to browsers. Modern Node.js supports both, though ES modules are increasingly the default going forward.
An iterator is an object that behaves similarly to a pointer, letting code step through the elements of a container one at a time without needing to know the specific internal details of how that particular container stores its data. Because every standard container provides iterators that behave in a broadly consistent way, the exact same generic algorithm, such as sorting or searching, can operate correctly on a vector, a list, or many other container types, without needing a separate version written specifically for each one.
__str__ controls how an object is displayed when printed for a human-friendly reader, __repr__ controls the more precise, developer-facing representation shown in a debugger or interactive session, __eq__ defines what it means for two objects of that class to be considered equal, and __hash__ defines how the object can be used as a dictionary key or stored in a set. Implementing these consistently is what lets a custom class behave naturally alongside Python's built-in types and collections.
The module pattern uses an immediately invoked function expression to create a private scope, exposing only a chosen set of functions or values while keeping everything else hidden from outside code. It was a common way to achieve encapsulation and avoid polluting the global scope before native ES modules existed, and the same underlying idea still shows up inside modern module files.
A vector stores its elements in one contiguous block of memory, which makes accessing any element by position extremely fast and also plays very well with the processor's cache, but inserting or removing an element in the middle requires shifting every element after it. A linked list stores elements scattered across memory, connected by pointers, making insertion and removal at any position fast without shifting anything, but accessing an arbitrary position requires walking through the list one link at a time, which is comparatively slow.
__str__ is meant to produce a readable, informal description of an object aimed at an end user, the kind of text you would want printed to a screen. __repr__ is meant to be unambiguous and, ideally, precise enough that evaluating it would recreate an equivalent object, aimed at developers debugging in a console. If only __repr__ is defined, Python falls back to using it for both purposes, which is why it is good practice to always implement it even when a friendlier __str__ also exists.
The singleton pattern ensures a particular object is only ever created once, with every part of the application sharing that same single instance rather than creating separate copies. In JavaScript this is often achieved simply by exporting an already-created object from a module, since a module's exports are cached and reused every time it is imported elsewhere in the program.
Operator overloading is commonly used to make a custom type behave naturally alongside the built in operators programmers already expect, such as overloading the plus sign so two custom vector or matrix objects can be added together directly, or overloading the equality comparison so two custom objects can be compared meaningfully with a familiar syntax. It is also frequently used to overload the stream insertion operator, allowing a custom object to be printed directly to the console in a readable, well formatted way.
Type hints let a function or variable declaration describe what type of value is expected, improving editor autocompletion and making the intent of the code clearer to anyone reading it. Crucially, Python itself does not enforce these hints at runtime at all, since it remains a dynamically typed language underneath; instead, a separate static analysis tool such as mypy is normally run against the codebase to actually catch type mismatches before the program ever executes.
A Web Worker runs JavaScript code on a separate background thread, away from the main thread that handles the user interface. This allows heavy computational work, like processing a large dataset or performing complex calculations, to run without freezing the page, since workers communicate with the main thread through messages rather than sharing memory directly.
Exception safety describes how gracefully a piece of code behaves when an exception is thrown partway through its execution. The basic guarantee promises the program remains in some valid, non corrupted state, without guaranteeing anything was actually accomplished. The strong guarantee promises that either the entire operation fully succeeds or it has no visible effect at all, leaving everything exactly as it was before. The no throw guarantee is the strongest, promising the operation will never throw an exception in the first place.
The property decorator lets a method be accessed using the same simple attribute syntax as a plain field, while still allowing custom logic to run behind the scenes whenever that value is read, and optionally when it is set or deleted. This is useful for adding validation or computed values to an attribute later on without breaking any existing code that already accesses it as if it were a plain, ordinary attribute.
Synchronous code runs one line at a time in order, with each line waiting for the previous one to finish before starting, which blocks everything else while a slow operation completes. Asynchronous code allows a slow operation, like a network request, to run in the background while the rest of the program continues, with the result delivered later through a callback, a promise, or await.
Static linking copies the actual code of any libraries a program depends on directly into the final executable file at build time, producing one larger, self contained file that needs nothing extra to run. Dynamic linking instead keeps library code in separate shared files on disk, and the program locates and loads them only when it actually starts running. Dynamic linking produces smaller executables and lets multiple programs share one copy of a library in memory, while static linking avoids depending on the correct library version being present on the target machine.
An instance method automatically receives the specific object it was called on as its first argument and can read or change that object's own data. A class method instead receives the class itself as its first argument, useful for logic that relates to the class as a whole rather than any one instance, such as an alternative constructor. A static method receives neither automatically and behaves like a plain function that has simply been grouped inside the class for organizational purposes.
Cross-site scripting, or XSS, is a vulnerability where an attacker manages to inject malicious JavaScript into a page that then runs in another user's browser, often by exploiting user input that gets inserted into the page without proper escaping. Front-end code that sets innerHTML directly from unsanitized user input is a classic way this happens, which is why frameworks and safe DOM APIs generally escape content by default.
Undefined behaviour refers to code whose outcome the C++ language standard deliberately places no requirements on whatsoever, meaning a compiler is technically free to make it do absolutely anything, including something that appears to work correctly, crash outright, or silently produce subtly wrong results. Common causes include reading past the end of an array, using an uninitialized variable, or dereferencing a pointer that no longer points to valid memory. Because the effects are unpredictable and can vary between compilers, undefined behaviour is generally treated as a serious bug that must be eliminated entirely.
An abstract base class defines a shared interface that subclasses are required to implement, using the abc module to mark certain methods as abstract so that Python actively prevents creating an instance of any subclass that has not provided a real implementation for each one. This is useful for enforcing a consistent contract across several related classes, catching a missing implementation immediately rather than letting it surface later as a confusing runtime error.
Cross-site request forgery, or CSRF, tricks a logged-in user's browser into unknowingly sending a request to a different site where they are authenticated, potentially performing an action like changing account settings without their consent. It is primarily defended against on the server with tokens that verify a request genuinely originated from the real application, though front-end code plays a role in correctly including those tokens with requests.
A dangling pointer is a pointer that still holds the address of memory that has already been freed or has otherwise gone out of scope, even though the pointer itself was never updated to reflect that. Using it afterward, either reading through it or writing through it, reaches into memory that may have already been reused for something completely different, producing unpredictable and often very hard to reproduce bugs. A common cause is returning a pointer to a local variable from a function, since that variable is destroyed the instant the function returns.
A common approach overrides the __new__ method on a class to check whether an instance has already been created and, if so, return that same existing instance instead of building a new one, effectively guaranteeing only one object of that class ever exists. A simpler alternative many Python developers reach for instead is just using a module-level variable, since a module is only ever imported once, which naturally gives the same single-instance guarantee with far less code.
Event delegation attaches a single event listener to a shared parent element rather than attaching a separate listener to every individual child element, relying on the fact that events bubble upward through the DOM. Inside the one handler, event.target identifies which specific child was actually interacted with. This is more efficient for long or dynamically changing lists, since new children are automatically covered without needing their own listener attached.
A memory leak occurs when a program allocates memory on the heap but loses every way of reaching it again, usually because the one pointer that referenced it was overwritten, went out of scope, or the corresponding delete call was simply forgotten, without the memory ever being released back to the system. In a long running program, repeated leaks gradually consume more and more available memory over time, eventually degrading performance or causing the program to run out of memory entirely. Smart pointers largely prevent this class of bug by automating the cleanup.
The factory pattern centralises object creation behind a function or method that decides which specific class to instantiate based on some input, rather than having calling code directly choose and construct a particular class itself. In Python this is often just a plain function that returns different class instances depending on a parameter, since Python's dynamic nature usually makes a full factory class hierarchy, common in more rigid languages, unnecessary overhead.
Shallow equality compares two values directly, meaning two objects are only considered equal if they are literally the exact same reference in memory, even if their contents look identical. Deep equality instead compares the actual contents of two objects or arrays recursively, considering them equal if every corresponding value matches, regardless of whether they are the same object in memory.
Stack unwinding is the process that occurs when an exception is thrown and no matching handler exists in the current function, causing the current function to exit immediately while properly running the destructors of any local objects it had created so far, before control passes up to the function that called it. This process repeats, function after function, until a matching catch block is finally found somewhere up the call chain, or the program terminates if none exists anywhere along the way.
Monkey patching means modifying or replacing a class or module's behaviour at runtime, after it has already been defined, often to fix or extend third-party code without touching its source. It is risky because the change is invisible to anyone reading the original code, can silently break if the patched library is later updated, and can cause confusing bugs if applied inconsistently across a codebase, so it is generally reserved for narrow, well-documented situations such as testing.
Memoization is an optimization technique where the result of an expensive function call is cached against its input, so that calling the function again with the same input returns the stored result immediately instead of recalculating it. It trades memory for speed and is especially effective for pure functions, whose output only ever depends on their input and never changes for the same arguments.
A lambda expression lets a programmer define a small, unnamed function directly at the point where it is needed, without having to write a separate, fully named function elsewhere just to use it once. This is especially convenient when passing a short piece of custom behaviour into a standard algorithm, such as describing exactly how two elements should be compared when sorting a collection, right there inline where the sorting call itself is written, keeping closely related code physically close together.
A virtual environment creates an isolated set of installed packages specific to one project, preventing dependency versions required by different projects on the same machine from conflicting with each other. Without one, installing a package globally can silently break another project that needed a different, incompatible version of the same library, and virtual environments make a project's exact dependencies easy to reproduce on another machine or in deployment.
A regular function gets its own this value, determined dynamically by how it is called, which can change depending on the calling context. An arrow function has no this of its own at all; it simply uses whatever this value existed in the surrounding scope where it was defined. This makes arrow functions predictable inside callbacks, such as inside a class method, where a regular function's this would otherwise unexpectedly change.
A capture list, written at the very start of a lambda expression, specifies which variables from the surrounding, enclosing scope the lambda is allowed to use inside its own body, and whether each one is captured by value, as an independent copy, or by reference, giving direct access to the original variable. Without listing a variable in the capture list, or capturing everything with a suitable shorthand, the lambda simply cannot see or use that outside variable at all from within its body.
A requirements file is typically just a flat list of package names and versions used to recreate an environment with a tool like pip, without describing anything about the project itself. A pyproject.toml file is a broader, standardized configuration file that can describe the project's metadata, its dependencies, and how it should be built and packaged, and modern Python tooling is increasingly consolidating around it as the single source of truth for a project's configuration.
A generator function, defined with an asterisk after the function keyword, can pause its own execution partway through and later resume exactly where it left off, rather than running straight through to completion like a normal function. Calling a generator function does not run its code immediately; instead it returns an iterator that produces one value each time its next method is called.
A mutex is the actual low level synchronization object that only one thread can hold, or lock, at any given time, used to protect a piece of shared data from being accessed by more than one thread simultaneously. A lock guard is a small wrapper object that locks a mutex the moment it is created and automatically unlocks it the moment it goes out of scope, following the same RAII pattern used elsewhere in C++, which prevents the easy mistake of forgetting to manually unlock a mutex after use.
The standard approach is profiling rather than guessing, using a tool such as cProfile to measure exactly how much time is spent inside each function during a real run of the program. This produces a breakdown showing which functions account for the bulk of the total time, letting effort focus on the actual bottleneck rather than optimizing code that was never a meaningful factor in the slowdown to begin with.
yield is used inside a generator function to pause execution at that point and return a value to whoever is calling the generator's next method. Execution stays paused there until next is called again, at which point the generator resumes right after the yield statement, allowing generators to produce a sequence of values over time rather than all at once.
A data race occurs when two or more threads access the same piece of shared memory at the same time, at least one of them is writing to it, and there is no synchronization mechanism, such as a mutex, coordinating that access between them. The resulting behaviour becomes genuinely undefined, potentially producing corrupted values, inconsistent results, or crashes that can be extremely difficult to reproduce reliably, since the exact outcome often depends on precise timing that can differ from one run of the program to the next.
Common strategies include replacing manual loops with built-in functions or comprehensions, which run faster since much of the work happens in optimized internal code rather than the Python interpreter itself, caching the results of expensive repeated calculations, choosing a more appropriate data structure such as a set instead of a list for membership checks, and, for genuinely CPU-heavy numerical work, offloading it to a library like NumPy that performs the heavy lifting in compiled code.
A Proxy wraps a target object and intercepts fundamental operations on it, such as reading a property, setting a property, or checking whether a property exists, allowing custom logic to run for those operations. It is used for things like validation, logging every access to an object, or creating reactive data structures that automatically detect when their properties change, which is how some front-end frameworks implement reactivity under the hood.
A C++ program first goes through preprocessing, where directives such as file inclusion and macro substitution are resolved into plain source code. Compiling then translates that source code into low level object code specific to the target machine, one source file at a time. Linking finally combines all the separate object files together, along with any required libraries, resolving references between them to produce a single, complete, runnable executable file. Each stage can fail independently, and error messages usually indicate which one is responsible.
The most common workaround is multiprocessing, which sidesteps the GIL entirely by running separate Python processes, each with its own interpreter and memory. Another option is delegating the CPU-heavy portion of the work to a library implemented in C, such as NumPy, which can release the GIL internally while it computes, allowing other Python threads to keep running in the meantime. A newer option in recent Python releases is an experimental mode that can disable the GIL altogether for true multithreaded parallelism.
const prevents a variable from being reassigned to point at a different value, but it says nothing about whether the object that variable points to can be modified internally, so its properties can still be changed freely. Object.freeze operates on the object itself, preventing any of its existing properties from being changed, added or removed, regardless of which variable or how many variables reference that object.
A preprocessor directive, always beginning with a hash symbol, is processed before actual compilation even begins and works purely as text substitution, such as inserting the contents of an included header file or replacing a macro name with its defined value everywhere it appears. A regular statement, by contrast, is genuine C++ code that the compiler itself understands, checks for correctness, and eventually translates into machine instructions. Preprocessor directives have no real awareness of C++ syntax or types at all, since they operate purely on raw text.
An iterable is any object capable of producing an iterator when passed to the iter function, such as a list or a string, but it does not track any position on its own. An iterator is the object actually returned by that call, which does keep track of its current position and produces the next value each time next is called on it, eventually raising a stop signal once no values remain. A for loop is essentially syntactic sugar for repeatedly calling next on an iterator obtained from an iterable.
Common approaches include minimizing and batching DOM updates rather than changing the page repeatedly in a loop, using debouncing or throttling on frequent events like scroll and resize, lazy-loading images and other off-screen content, reducing the size and number of JavaScript bundles sent to the browser, and using browser developer tools to profile exactly which function or render step is actually consuming the most time before optimizing blindly.
Name mangling is the process by which a C++ compiler encodes extra information, such as a function's parameter types and the class it belongs to, directly into the internal name used for that function within the compiled object file. This allows the linker to correctly distinguish between several overloaded functions that share the same visible name in the source code but differ in their parameters. It also explains why C++ code often needs a special declaration to interoperate cleanly with code compiled using the plain C convention, which does not mangle names at all.
lru_cache is a decorator that automatically remembers the results of previous calls to a function based on its arguments, returning the cached result instantly instead of recomputing it if the same arguments are seen again. It is especially useful for expensive, pure functions that are called repeatedly with a limited set of inputs, such as recursive calculations, though it should be avoided on functions whose results depend on anything beyond their arguments, since a stale cached answer could then be returned incorrectly.
Tree shaking is a build-time optimization where a bundler analyzes which parts of a module are actually imported and used, then eliminates the unused exports entirely from the final bundle. It relies on the static, analyzable structure of ES module imports and exports, which is one practical reason ES modules are preferred over CommonJS for library code intended to be bundled efficiently.
A shallow copy duplicates an object's member variables exactly as they are, meaning that if the original object held a pointer to some external data, the copy ends up holding a pointer to that very same external data rather than its own independent version. A deep copy instead also duplicates whatever that pointer refers to, producing a genuinely independent copy with no shared underlying data at all. Classes managing their own raw resources typically need a custom copy constructor to perform a proper deep copy correctly.
Chaining one exception from another, by raising a new exception with a from clause pointing at the original one, preserves the original exception as context while still surfacing the new, often more specific one to the caller. This produces a traceback showing both the low-level cause and the higher-level error it triggered, which is far more useful for debugging than losing the original exception entirely when translating it into a different one.
Imperative code describes the exact step-by-step instructions for how to accomplish something, such as manually creating an element, setting its attributes, and appending it to the page one operation at a time. Declarative code instead describes what the final result should look like, leaving the how up to something else. React embraces this by letting developers describe the desired UI for a given state, while React itself figures out the actual DOM operations needed to get there.
A copy constructor is a special constructor that creates a new object as a copy of an existing object of the very same class, and it is called automatically whenever an object is passed by value into a function, returned by value from one, or explicitly initialized directly from another existing object. If a class does not define its own copy constructor, the compiler quietly generates a default one that performs a simple shallow copy, which is only correct for classes that do not manage any external resources themselves.
Without a custom __eq__ method defined, Python falls back to comparing objects purely by identity, meaning two separate objects are only considered equal if they are literally the exact same object in memory, regardless of how similar their attributes look. To get meaningful value-based equality for a custom class, __eq__ needs to be implemented explicitly to compare the relevant attributes directly, and __hash__ often needs defining alongside it if the objects are meant to be used in a set or as dictionary keys.
A pure function always returns the same output for the same input and produces no observable side effects, such as modifying an external variable, changing its arguments, or making a network request. Pure functions are easier to test, reason about and reuse safely, since calling one never depends on or affects anything outside of the values explicitly passed into it.
A move constructor creates a new object by transferring ownership of resources away from a temporary or otherwise disposable object, rather than duplicating that data the way an ordinary copy constructor would. It typically works by simply copying an internal pointer or handle from the source object and then resetting the source to a safe, empty state, avoiding the cost of an actual data copy entirely. This is particularly valuable for objects that manage large amounts of dynamically allocated memory internally.
A race condition occurs when two or more threads access and modify shared data at the same time in a way that makes the final outcome depend on unpredictable timing, often producing incorrect results that are hard to reproduce consistently. A lock forces only one thread at a time to enter a protected section of code, so operations on shared data happen safely one after another rather than getting interleaved unpredictably between multiple threads.
Immutability means data is never changed after it is created; instead, any update produces a brand new copy with the change applied, leaving the original untouched. Many front-end frameworks rely on this to efficiently detect changes, since comparing whether two references are identical is far cheaper than deeply comparing every field, and it also prevents an entire category of bugs caused by unexpected shared mutation.
Inheritance models an is a relationship, where a derived class genuinely is a more specific kind of its base class and automatically gains its behaviour. Composition instead models a has a relationship, where one class simply contains another class as a member variable and reuses its behaviour by explicitly calling into it, without pretending to actually be that other class. Composition is often favoured over inheritance in modern C++ design because it tends to produce more flexible, less tightly coupled relationships between classes.
A deque, from the collections module, is a fast double-ended structure but is not inherently safe for multiple threads to use without additional locking of your own. The queue module provides thread-safe queue implementations specifically designed for passing data safely between threads, already handling the necessary internal locking, which makes it the more appropriate choice whenever multiple threads need to hand work off to each other rather than a plain unprotected deque.
A Map holds strong references to its keys, meaning an object used as a key will not be garbage collected as long as the Map still exists, even if nothing else references it. A WeakMap holds its keys weakly, allowing them to be garbage collected once nothing else references them, which makes WeakMap well suited for attaching extra data to an object without accidentally preventing that object from ever being cleaned up.
A static member variable belongs to the class itself rather than to any single object of that class, meaning every object shares exactly one common copy of it, and it exists even before any object has been created. A static member function similarly belongs to the class as a whole, can be called without needing an actual object to call it on, and can only access other static members directly, since it has no particular object's data of its own to work with.
Global mutable state shared across requests or tasks in a long-running service can lead to subtle bugs where one request's data leaks into or corrupts another's, especially once multiple threads or asynchronous tasks are involved and the assumption that only one operation runs at a time no longer holds. It also makes testing harder, since tests can accidentally influence each other through leftover shared state, which is why most frameworks encourage keeping request-specific data scoped locally rather than stored globally.
A service worker is a script that runs in the background, separate from the page itself, capable of intercepting network requests, caching assets for offline use, and enabling features like push notifications. It forms the technical foundation of progressive web apps, letting a website continue to function, at least partially, even without a network connection.
Overloading means defining several functions that share the same name but differ in their parameter lists, and the compiler decides which one to call based purely on the arguments provided, resolved entirely at compile time. Overriding means a derived class provides its own specific implementation of a virtual function already defined in its base class, keeping exactly the same name and parameters, and the correct version to actually run is decided at runtime based on the real type of the object involved.
asyncio helps specifically with I O bound workloads, where a program spends significant time waiting on external things such as network requests, database queries or disk access, since it can start many such operations and let the event loop switch between them while each one waits, rather than sitting idle on one at a time. It provides no benefit at all for CPU-bound work, since a single core is still doing the actual computation and there is nothing to overlap while it is busy calculating.
With client-side rendering, the browser receives a mostly empty HTML page and JavaScript builds the actual content in the browser after loading, which can delay the first meaningful paint but keeps subsequent navigation fast. With server-side rendering, the server generates the full HTML for a page before sending it, so content appears immediately and search engines can read it more easily, often at the cost of a heavier server workload per request.
Polymorphism means that the same piece of code, such as a single function call written once, can behave differently depending on the actual type of object it is operating on at that moment. C++ achieves this kind of runtime polymorphism through virtual functions: calling a virtual function through a base class pointer or reference automatically invokes whichever specific version the real, underlying object's class has overridden, decided dynamically at the moment the program actually runs, rather than being fixed once and for all at compile time.