Python Interview Questions and Answers

This blog provides details on most frequently asked interview questions and answers on Python.

Enlisted below are the most commonly asked interview questions and answers on Python programming language.

  1. Is Python interpreted or compiled? Are there ways to compile the code?
  2. Which is faster in python — Searching in a list or a dictionary. And why?
  3. How can we get the code of a python object?
  4. What are the ways to make python code work faster?
  5. What is exec function and how we can use it?
  6. What are metaclasses and dataclasses in python?
  7. what is __call__ method in python?

Let’s Explore one by one!!!

Q #1. Is Python interpreted or compiled? Are there ways to compile the code?

Ans: When we instruct Python to run our script, there are a few steps that Python carries out before our code actually starts crunching away:

It is compiled to bytecode.

Then it is routed to virtual machine.

When we execute a source code, Python compiles it into a byte code. Compilation is a translation step, and the byte code is a low-level platform-independent representation of source code. Note that the Python byte code is not binary machine code (e.g., instructions for an Intel chip).

Actually, Python translates each statement of the source code into byte code instructions by decomposing them into individual steps. The byte code translation is performed to speed execution. Byte code can be run much more quickly than the original source code statements. It has.pyc extension and it will be written if it can write to our machine.

So, next time we run the same program, Python will load the .pyc file and skip the compilation step unless it's been changed. Python automatically checks the timestamps of source and byte code files to know when it must recompile. If we resave the source code, byte code is automatically created again the next time the program is run.

If Python cannot write the byte code files to our machine, our program still works. The byte code is generated in memory and simply discarded on program exit. But because .pyc files speed startup time, we may want to make sure it has been written for larger programs.

Let's summarize what happens behind the scenes. When a Python executes a program, Python reads the .py into memory, and parses it in order to get a bytecode, then goes on to execute. For each module that is imported by the program, Python first checks to see whether there is a precompiled bytecode version, in a .pyo or .pyc, that has a timestamp which corresponds to its .py file. Python uses the bytecode version if any. Otherwise, it parses the module's .py file, saves it into a .pyc file, and uses the bytecode it just created.

Byte code files are also one way of shipping Python codes. Python will still run a program if all it can find are.pyc files, even if the original .py source files are not there.

Python Virtual Machine (PVM)

Once our program has been compiled into byte code, it is shipped off for execution to Python Virtual Machine (PVM). The PVM is not a separate program. It need not be installed by itself. Actually, the PVM is just a big loop that iterates through our byte code instruction, one by one, to carry out their operations. The PVM is the runtime engine of Python. It's always present as part of the Python system. It's the component that truly runs our scripts. Technically it's just the last step of what is called the Python interpreter.

Q #2. Which is faster in python — Searching in a list or a dictionary. And why?

Ans: In Python, a dictionary is an unordered and mutable Python container that stores mappings of unique keys to values. Dictionaries are written with curly brackets ({}), including key-value pairs separated by commas (,). A colon (:) separates each key from its value.

The Dictionary uses hashing to search for the data. A Dictionary first calculated a hash value for the key and this hash value leads to the target data bucket. After that, each element in the bucket needs to be checked for equality. But actually the list will be faster than the dictionary on the first item search because nothing to search in the first step. But in the second step, the list has to look through the first item, and then the second item. So each step the lookup takes more and more time. The larger the list, the longer it takes

Q #3. How can we get the code of a python object?

Ans: As we know, everything in python is an object, even function we define is also an object in Python. As a programmer, we write so many functions and also do use functions written by others. When we define the function, we know what is written in function and how exactly it works, but when we use functions of other module we don’t know what’s the source code of it.

We will learn method to get source code of functions in Python.

To get the source code of functions in python, use inspect module. Inspect module have a set of functions using which you can get source code, documentation string, and path of file where method is defined.

Let’s understand it with a simple example:

```
import inspect
import random
print(inspect.getsource(random.randint))
```

Output:

```def randint(self, a, b):
“””Return random integer in range [a, b], including both end points.
“””

return self.randrange(a, b+1) ```

But one thing to keep in mind, inspect won’t return the source code of built-in objects and object defined interactively.

To get the code of object defined interactively you can use dill.source.getsource function. Built-in methods of Python is written in C and can only be access by directly looking into python source code.

Q #4. What are the ways to make python code work faster?

Ans: The design of the Python language enables us to make almost anything dynamic. We can replace the methods on objects at runtime, we can monkey-patch low-level system calls to a value declared at runtime. Almost anything is possible. So not having to declare the type isn’t what makes Python slow, it’s this design that makes it incredibly hard to optimize Python.

PyPy is claimed to be the fastest implementation for Python with the support of popular Python libraries like Django and is highly compatible with existing Python code. PyPy has a GIL and uses JIT compilation so it combines the advantages of both making the overall execution a lot faster than CPython. Several studies have suggested that it is about 7.5 times faster than CPython.

PyPy first takes our Python source code and converts it to RPython which is a statically-typed restricted subset of Python. RPython is easier to compile into more efficient code as its a statically-typed language. PyPy then translates the generated RPython code into a form of bytecode, together with an interpreter written in the ‘C’ programming language. Much of this code is then compiled into machine code, and the bytecode runs on the compiled interpreter.

Here’s a visual representation of this implementation:

It also allows for pluggable garbage collectors, as well as optionally enabling Stackless Python features. Finally, it includes a just-in-time (JIT) generator that builds a just-in-time compiler into the interpreter, given a few annotations in the interpreter source code. The generated JIT compiler is a tracing JIT. This was a brief explanation of how the implementation works.

“If you want your code to run faster, you should probably just use PyPy.” — Guido van Rossum (creator of Python)

Q #5. What is exec function and how we can use it?

Ans: Basically, the Python exec() method executes the passed set of code in the form of string. It is very useful as it practically supports dynamic execution.

In another words, the python exec() function is used for the dynamic execution of Python program which can either be a string or object code and it accepts large blocks of code, unlike the eval() function which only accepts a single expression.

Syntax:

exec(object[, globals[, locals]])

Q #6. What are metaclasses and dataclasses in python?

Ans: Python metaclass is a class that instantiates a class. In python, a class is actually an object of another class. This another class is called metaclass. Metaclass in python defines the behaviors of class objects. let’s look at some examples to understand the metaclass concept clearly.

Python built-in Metaclass

type is a built in metaclass in python. Let’s start with the following example:

class SampleClass():
pass
obj = SampleClass()
print(type(obj))

In the above code we have created a class named SampleClass, and creating an object of it. Then type of object says:

class '__main__.SampleClass'

That means obj is an object of SampleClass. Now if we try to see the type of SampleClass itself as following:

print(type(SampleClass))

Then the output is:

class 'type'

That means SampleClass is an object of class type. To be more specific SampleClass is an instance of class type. So type is a metaclass. Every class of python belongs to the built-in metaclass type.

How python metaclass works?

Whenever we create any class then the default metaclass gets called. This metaclass gets called with three information — name of the class, set of base classes of the class and the attributes of the class.

As type is the builtin metaclass, whenever we create a class type gets called with these three argument.

We are saying that every class in python is also a object of type, which means we can create any class in a single line just like we create object of any class. This way of creating a class is called “creating class on the fly”.

Dataclass

Dataclasses, introduced in Python 3.7 (and backported to Python 3.6), provide a handy way to make classes less verbose. Many of the common things you do in a class, like instantiating properties from the arguments passed to the class, can be reduced to a few basic instructions.

Example

Here is a simple example of a conventional class in Python:

class Book:
'''Object for tracking physical books in a collection.'''
def __init__(self, name: str, weight: float, shelf_id:int = 0):
self.name = name
self.weight = weight # in grams, for calculating shipping
self.shelf_id = shelf_id
def __repr__(self):
return(f"Book(name={self.name!r},
weight={self.weight!r}, shelf_id={self.shelf_id!r})")

The biggest headache here is the way each of the arguments passed to __init__ has to be copied to the object’s properties. This isn’t so bad if you’re only dealing with Book, but what if you have to deal with Bookshelf, Library, Warehouse, and so on? Plus, the more code you have to type by hand, the greater the chances you’ll make a mistake.

Here is the same Python class, implemented as a Python dataclass:

from dataclasses import dataclass@dataclass
class Book:
'''Object for tracking physical books in a collection.'''
name: str
weight: float
shelf_id: int = 0

When you specify properties, called fields, in a dataclass, @dataclass automatically generates all of the code needed to initialize them. It also preserves the type information for each property, so if you use a code linter like mypy, it will ensure that you’re supplying the right kinds of variables to the class constructor.

Q #7. what is __call__ method in python?

Ans: Python has a set of built-in methods and __call__ is one of them. The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).

object() is shorthand for object.__call__()

Example 1:

class Example:
def __init__(self):
print(“Instance Created”)

# Defining __call__ method
def __call__(self):
print(“Instance is called via special method”)

# Instance created
e = Example()

# __call__ method will be called
e()

Output :

Instance Created
Instance is called via special method

Thank you for reading my blog, keep learning!!

Passionate about ML