Skip to content

Boarding pass · Python Advanced

Python · Advanced interview

An AI mock interview for senior Python engineers. Reason about the GIL and concurrency models, CPython memory management, metaprogramming with metaclasses and descriptors, and how to profile and speed up real Python.

20–30 minEstimated6 questionsTailored live12 model answersTo study
  • Voice interview
  • Live feedback
  • Browser-only
  • No installation required

Your report · sample

AI Readiness Score

/100
Content score English score

Finish the mock and get this report — scored on content and English, with concrete tips and a model answer for every question, plus a study plan.

Your flight path

Five steps to interview-ready.

From a quick warm-up to a personalised study plan — here's the whole loop, and what you get at each gate.

  1. Step 01

    Preparation

    Skim the topics and warm up — you're briefed before takeoff.

  2. Step 02

    AI Interview

    A realistic AI interviewer asks tailored questions — answer by voice or text.

  3. Step 03

    Instant Score

    Finish and get a 0–100 readiness score across content and English.

  4. Step 04

    AI Feedback

    Concrete tips and a rewritten model answer for every response.

  5. Step 05

    Study Plan

    A personalised plan targets your weakest areas — so the next run scores higher.

Preview the AI demo

See one answer scored, end to end.

The whole loop on sample data — question, your answer, instant feedback and a study plan. Hover to pause.

aevrofy.com/session · live demoPlaying

Interviewer · Question 1

“Tell me about yourself.”

Who it's for

  • Senior Python engineers
  • Devs who design Python frameworks/libraries
  • Anyone targeting senior/lead Python roles
  • Engineers who profile and optimize Python

What you'll practice

  • Choosing threads, processes or asyncio
  • Reasoning about the GIL and memory
  • Metaclasses, descriptors and the MRO
  • Profiling and speeding up Python

Topics covered

What this level expects.

Concurrency

  • The GIL
  • Threads/processes/asyncio
  • Coroutines

Internals & memory

  • Reference counting & GC
  • Everything is an object
  • __slots__

Metaprogramming

  • Metaclasses
  • Descriptors
  • MRO & super

Performance

  • Profiling
  • Why Python is slow
  • Vectorization & C

Practice questions

12 questions, with model answers.

Read them, then run the live mock to answer out loud and get scored. Tap any question to reveal a model answer.

01What is the GIL and what are its practical implications?

The Global Interpreter Lock is a mutex in CPython that lets only one thread execute Python bytecode at a time, protecting the interpreter's memory management. The implication: threads don't give you parallel speedup for CPU-bound Python code, but they're fine for I/O-bound work because the GIL is released during blocking I/O. CPU parallelism needs multiprocessing or C extensions that release the GIL. (Recent CPython has experimental free-threaded builds that remove it.)

02When do you choose threading, multiprocessing, or asyncio?

asyncio for high-concurrency I/O with cooperative tasks in one thread (thousands of sockets) when your libraries are async. threading for I/O-bound work with blocking libraries, where the GIL releases during I/O. multiprocessing (or a process pool) for CPU-bound work, to get true parallelism across cores at the cost of memory and inter-process communication. The deciding question is I/O-bound vs CPU-bound, then library support.

03How does asyncio actually run coroutines?

A coroutine (async def) is a function you can pause at await points. The event loop runs a single thread, switching between coroutines whenever one awaits something not yet ready, so many I/O operations overlap without threads. The catch is cooperative scheduling: a coroutine that does blocking work or heavy CPU without awaiting starves the loop, so blocking calls must be offloaded to an executor.

04How does CPython manage memory?

Primarily by reference counting — each object tracks how many references point to it and is freed immediately when that hits zero. Because reference counting alone can't reclaim reference cycles, a generational cyclic garbage collector periodically finds and frees unreachable cycles. CPython also pools small objects and integers. Knowing this explains why deleting a name doesn't always free memory and why cycles need the GC.

05What does 'everything is an object' mean in Python, and why does it matter?

Functions, classes, modules, and even types are first-class objects with attributes you can pass around, reassign, and introspect. Variables are names bound to objects, not boxes holding values, so assignment binds a name and 'mutating through one name' is visible through another bound to the same object. This model underlies decorators, higher-order functions, monkey-patching, and the aliasing gotchas with mutable defaults.

06What does __slots__ do and when would you use it?

By default each instance stores attributes in a per-instance __dict__, which is flexible but memory-heavy. Declaring __slots__ with a fixed set of attribute names tells Python to store them in a compact structure instead, saving significant memory and slightly speeding attribute access — valuable when you create millions of small objects. The trade-off is you can't add arbitrary attributes and it complicates multiple inheritance.

07What is a metaclass and when would you actually need one?

A metaclass is the 'class of a class' — it controls how classes are created, the way a class controls how instances are created (type is the default). You'd use one to enforce constraints on subclasses, auto-register classes, or inject methods at class-creation time, as ORMs and frameworks do. In practice most needs are now met by __init_subclass__ or class decorators, so genuine metaclasses are rare.

08What is a descriptor, and how does property use one?

A descriptor is an object implementing __get__/__set__/__delete__ that, when assigned to a class attribute, customizes what attribute access does. property is a built-in descriptor that routes attribute reads/writes through getter/setter functions. Descriptors are the machinery behind property, classmethod, staticmethod, and ORM fields — they're how 'an attribute' can run code.

09How does the method resolution order work with multiple inheritance?

Python computes a linear order of classes (the MRO) using the C3 linearization, which respects the order of base classes and ensures each ancestor appears after its subclasses. super() follows this MRO rather than just the literal parent, so in a diamond hierarchy a cooperative super() call visits each class once. You can inspect it via Class.__mro__; understanding it is key to making multiple inheritance behave.

10How do you profile and then optimize a slow Python program?

Measure first: cProfile for function-level hotspots, line_profiler for line-level, and a memory profiler if memory is the issue — never guess. Then attack the actual hotspot: better algorithms/data structures, caching (lru_cache), moving tight loops to vectorized NumPy or a C extension, reducing per-call overhead, and only then concurrency. Re-measure after each change.

11Why is pure Python slow, and how do high-performance libraries get around it?

CPython is an interpreter with dynamic typing and per-operation object overhead, so tight numeric loops pay a heavy cost per element. Libraries like NumPy, pandas, and ML frameworks push the loop down into precompiled C/Fortran that operate on contiguous arrays and release the GIL, so you express the work as vectorized operations instead of Python loops. Tools like Cython, Numba, and writing C extensions do the same for custom hotspots.

12How do you keep a large Python codebase maintainable with type hints?

Add type hints and run a static checker (mypy/pyright) in CI to catch type errors the dynamic runtime won't. Type the public boundaries first, use precise types (Protocol for structural interfaces, generics, Literal/TypedDict) where they add safety, and gate new code as strict while incrementally typing legacy. Hints also improve editor support and serve as living documentation, at the cost of some upfront annotation effort.

Preparation tips

Walk in ready.

  • Be able to say which workloads the GIL does and doesn't hurt
  • Explain a real asyncio vs threads decision
  • Know how reference cycles get collected
  • Have a concrete profiling-then-optimizing story

Ready for the real thing?

Run a 6-question Python mock interview, answer out loud, and get a readiness score with tips and model answers.

More advanced interviews

Aevrofy · Python advanced interview prep