Python is one of the most in-demand programming languages nowadays, so senior Python developer interview questions are among the most frequently asked when applying for remote Python developer jobs. Python is easy to learn, has a great community of developers, and is practiced in many fields such as software engineering, automated testing, machine learning, back-end engineering, and web scraping.
Below you can find some of the most important and frequently asked senior Python developer interview questions and answers. Please remember that these questions are for Python Core and don’t consider other application development aspects, issues, or skills (you can check out these in our guide to senior software engineer interview questions).
1. What can be the keys of a dictionary in Python?
When answering this interview question, a junior Python developer candidate may answer None, strings, or numbers. A mid-level developer may mention booleans, tuples, or any immutable object. However, a senior Python developer is expected to answer that any hashable object can be the key of a dictionary.
Any hashable object is immutable. As an example, the code below is correct as this tuple and all of its elements are hashable. Please be aware that sets, dictionaries, and lists are not hashable, therefore cannot be the keys of a dictionary.
2. What is CPython?
Python is an interpreted language. Its code is first interpreted by another program (interpreter) and then compiled into something called bytecode. Bytecode is made out of bytes that represent the machine’s instructions. CPython is the implementation of Python whose bytecode is in the C programming language.
On the other hand, we have Jython which bytecode is in Java or other Python implementations.
We also have something called Cython, which is the compiled language used to create CPython extensions. The Cython language is a superset of Python that supports several C programming language features.
3. What is LEGB in Python?
This is an example of sr Python developer interview questions related to scoping. When the Python interpreter is trying to look up a name, it uses the LEGB rule to resolve the names (variable, function, and other object names). It first checks for the existence of names in L, E, G, and B scopes in the order below:
- Local Scope: The area within a function body or a lambda expression.
- Enclosing Scope: Assume we have a function called outer which has a nested function. Enclosing scope (or nonlocal scope) is the area within the body of outer function.
- Global Scope: The names in this scope are visible to all code in one Python script (in one file having a .py extension).
- Built-in Scope: The names that exist in this scope are loaded when we run a Python shell/script. Keywords such as in, and, or, def, class and expressions like __main__, __file__ are some examples.
4. What are the usages of nonlocal and global keywords in Python?
This interview question has a direct relationship with the previous one. The code sample below illustrates the usage of these two keywords:
5. What is GIL and why is it important?
GIL is one of the most controversial and important features of the CPython-based implementation of Python. GIL, or Global Interpreter Lock, is a construct/tool that makes sure that only one thread at a time can execute a Python program. In other words, this lock belongs to the Python interpreter and it uses it to lock a thread.
For example, thread T1 acquires GIL and does its job. While the Python interpreter is using GIL to lock T1, all other threads have to wait. After T1 finishes, it releases GIL and passes it to another thread T2 that needs it. The reason for the GIL presence is to make CPython thread-safe and not allow some threads to interfere with one another.
6. How does Python handle memory management?
Before answering senior Python interview questions like this one, you must be aware that we are talking about the CPython implementation. Other Python implementations may have different rules and requirements for memory management.
Assume you have a Python script and you want to execute it. When you execute this file, the Python interpreter occupies some “area” of the RAM. This “area” itself is divided into two categories: the stack and the private heap.
Now assume that in this script we have declared a string object a = “hello”. When we execute this script, the CPython memory management system creates an object of type string on the private heap. This object contains three fields:
- Type: This is a string (note that Python is a dynamically typed programming language, so it will understand your object type to store).
- Value: This is “hello”.
- Reference count: It shows the number of times that a has been referenced. For now, it is 1.
Now on the stack, the reference to a (that is stored on the private heap) is stored. There exists a tool called a garbage collector. The garbage collector’s job is to delete the objects (on the private heap) that are no longer referenced, meaning, it deletes the objects whose reference count reached zero. This way the garbage collector frees up some memory space for the Python interpreter.
7. Where should we use Python's multithreading, multiprocessing, and asyncio libraries?
To answer this question, we need some background knowledge. We divide the operations that we want our Python code to do into two categories:
- CPU-bound operations such as parsing, image processing, string manipulation, and algorithms involving heavy calculations. We can use parallelism for these types of operations. Basically, parallel programming is when we create different processes to divide a job among them and they all do the job simultaneously. Each process has its own GIL, Python interpreter, memory space, and state information. In Python, we use the multiprocessing library to achieve parallelism.
- IO-bound operations such as sending HTTP requests, querying data from databases, sending emails, and opening a file. We use concurrency for these operations. In Python, we can handle these operations using multithreading and asyncio libraries. Note that parallelism requires more resources than concurrency.
8. How does importing in Python work?
To answer this senior Python developer interview question, assume we have a directory called dir, inside which we have a Python script. When you import a module in this Python script, the Python interpreter tries to find your imported module in this order:
- It searches among other Python scripts inside the dir directory.
- Then it goes over the list of the directories that are set using the PYTHONPATH environment variable.
- Last, it searches through the default directories where Python files were installed. For example, 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python311\\Lib'
9. What is a closure in Python?
A closure is an inner/nested function that keeps the data regarding its enclosing scope even after the closure is called. To illustrate your answer to this interview question, you can provide this scenario for using closures for lazy evaluation:
10. How do you write scalable code in Python?
This is one of the most impactful and advanced senior Python interview questions. Scalability means creating services and microservices that can handle millions of users (large loads) without going down. This is a challenge that must be handled properly and writing scalable code is one way to make our service scalable.
Please be aware that we have to take into account many other components of creating a scalable project, such as systems design, DBMS, and infrastructure.
Below you can find some concepts of writing scalable code for Python Core to include in your answer to this interview question.
Use efficient data structures. For example, the time complexity of in operator is different depending on what iterable it has been used on.
- On list/tuple 🡪 O(n) time complexity.
- On dictionary/set 🡪 O(1) is the average case and O(n) is the worst case.
In the examples above, n is the length of the iterable.
Use parallelism. Dividing and running a CPU-bound operation using different processes can be a solution to boost the speed.
Design a distributed system. In a distributed system there are different machines that communicate with each other to do a job. Using libraries like Apache Spark or Ray can be a good approach for scalability.
Use caching. Assume there is an image that requires heavy processing and this image must be sent to many users. To address such requirements, we can process this image only once and cache/store the processed version in a variable. This way whenever we want this processed image, we can just make use of that variable and avoid processing the image again.
Those were the top ten senior Python developer interview questions and answers for those looking to advance their career in tech. You can get more information about frequently asked technical interview questions in our comprehensive guide for dozens of roles and specializations to help you secure a job offer. Check it out: