Python Interview questions in 2019-2020


This article is an attempt at compiling the most common Python interview questions asked at the beginner or intermediate level. Bookmark and go through our list of questions and answers whenever you are preparing for an interview or when you just want to increase your Python mastery.

Python is increasing its market share by leaps and bounds and is in very high demand. If you are field of Web development, Machine Learning, Artificial Intelligence, Blockchain, Cloud or Data Analytics, Python is your best bet. The language is easy to learn and master. However, like all other languages, there is a Pythonic way to write code and some specific functionalities which are not found in most other languages. These things are what form the part of an advanced level Python interview. I have experience of giving not less than 20 interviews in the last year and this article is an attempt to document all those questions. The solutions are not guaranteed to be correct and should be verified by yourself.

This is still a WIP so some questions are still not answered but will be answered soon.

Q. Different Data types in Python
A. Data types in Python can be divided into two primary parts - Mutable and Immutable data types.
Mutable data types are those which can be changed on runtime. Examples of such data types are list, set, dict.
Immutable data types, on the other hand, are those which cannot be modified on runtime like int, float, bool, str, tuple and unicode.
Let's understand this in a better way with an example:

mylist = [1,2,3,4,5]  #create a list
mylist.append(6) #Append a new value which has changed the list structure
mytuple = (1,2,3,4,5)
mytuple.append(6) #This will thrown an error since a tuple has no method called "append" since it is a immutable data type


Q. What is the difference between a list and a tuple and how to decide which one to use?
A. A list is a Mutable data type whereas a Tuple is an Immutable data type. It means that List should be used when you want to modify the list information during runtime of the program.
Tuples, on the other hand, are a fixed list of values which should be used when your list of values is going to stay consistent through the runtime of the program. Tuples being Immutable data type, take less memory in the storage compared to Lists which have to allocate some extra memory always to make the addition of values faster.
List as defined with a square bracker, eg:
mylist = [1,2,3,4]
Tuples are defined with Round brackets, eg:
mytuple = (1,2,3,4)
Tuple can also be defined without using the brackets
list_of_values = 1,2,3,4 #A list if values defined like this is also a tuple
type(list_of_values)


Q. How do you create an Abstract Class in Python
A. Abstract classes are classes that contain one or more Abstract methods. These methods cannot be instantiated and must be overridden by subclasses.
Python natively doesn't support Abstraction but there is a module named "ABC" which provides the capability of Abstraction.
The important thing to note here is that it is possible to implement some functionality in the Abstract class method though it has to be overridden by the subclass. And like in normal Inheritance, you can use the super() method to use the functionality defined in the Base class.

from abc import ABC, abstractmethod

class AbstractClass(ABC):
def __init__(self):
super().__init__()
pass

@abstractmethod
def some_method(self):
print("hello")

class AbstractChild(AbstractClass):
pass
my_obj = AbstractChild() #This is going to throw an error "TypeError: Can't instantiate abstract class AbstractClass with abstract methods some_method
"

The correct way to do this:
from abc import ABC, abstractmethod

class AbstractClass(ABC):
def __init__(self):
super().__init__()
pass

@abstractmethod
def some_method(self):
print("hello")

class AbstractChild(AbstractClass):
def some_method(self):
super().some_method()

my_obj = AbstractChild()
my_obj.some_method()

Q. Can a dictionary contain duplicate keys? Explain in detail
A. A Dictionary by its definition contains only unique keys. For this purpose, it uses the Python inbuilt hash function to generate the hash of the keys and store in the memory. Due to this reason, only Immutable data type is allowed as Python dictionary keys like tuple, int, str, etc. An important thing to note is that if a Tuple contains a Mutable data type as its elements like a dictionary or a list, then the Tuple cannot be used as a Python dictionary key.

Q. How to generate a list in a single line
A. We can generate a list using a single line of code by using List Comprehension. This involves writing a small piece of code which will generate multiple values and putting square brackets outside. Example:
>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

If you make use of Round brackets instead of the Square brackets, we get a Generator instead of a List.
>>> a = (i for i in range(10))
>>> a
<generator object at 0x7f49efe0f840>

Q. What are Python Generators and when are they used
Python Generators are an easy way to create iterators. It helps you avoid the complex implementation of creation an __iter__(), creating __next__() method and then raising StopIteration exception when values have been exhausted. However, the bigger advantage is the memory optimization it offers.
Generators don't evaluate all the values immediately but return a generator object. This object can be used in a for loop to keep on generating values rather than a list of values and hence only 1 value at a time exists in the memory. This is achieved by using one or more yield statements instead of return. Yield suspends the execution of the loop and returns a single value. Only when it is called again is the next value evaluated and returned. This keeps on going until the values are exhausted and the StopIteration is raised automatically after it.
def mygen(i):
#This will print all the odd values
for j in range(i):
if j % 2 != 0:
yield j
#This will print all the even values
for j in range(i):
if j % 2 == 0:
yield j
for values in mygen(5):
print(values)

Output:
ankit@MYPC $ python test.py
1
3
0
2
4

We can also use the __next__() method to go through the values. To do so, let's modify the code a little bit and see the execution in a Python console:
Code:
def mygen(i):
#This will print all the odd values
for j in range(i):
if j % 2 != 0:
yield j
#This will print all the even values
for j in range(i):
if j % 2 == 0:
yield j

Output:
ankit@MYPC $ python
Python 3.7.0 (default, Jun 28 2018, 13:15:42)
[GCC 7.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from test import mygen
>>> mygen(5)
<generator object mygen at 0x7f006475f9a8>
>>> a = mygen(5)
>>> a.__next__()
1
>>> a.__next__()
3
>>> a.__next__()
0
>>> a.__next__()
2
>>> a.__next__()
4
>>> a.__next__()
Traceback (most recent call last):
File "", line 1, in
StopIteration

Q. What is the difference between xrange and range?
A. "range" in Python 3 is what was "xrange" in Python 2. It is basically a generator implementation that saves memory by evaluating values when they are required. While the "range" of Python 3 is a little bit slower than "xrange" in Python 2, it is due to the improvements that were brought to the Python 3 "range" implementation.
"range" in Python 2 on the other hand, is an iterator implementation which evaluated all the values at once and stored it in memory to be used in the program wherever required.

Q. What is "closure" in Python and when do you use it?
A. Closure in Python is a way to attach some data to code. Let's understand this in a better way by way of a small code:
def func2(func):
print("Inside func2")
def func(mystr):
print("Inside func")
print(mystr)
return func #note that we are returning a function here but not executing it

a =func2(func) #Here we are storing the reference of a function in a variable along with a argument.
a("function call")

Output:
Inside func2
Inside func
function call

The first line of output is generated by a =func2(func). The rest of the 2 lines are generated by the last line of the code a("function call"). When we assign func2 to a, we also pass an argument and that is stored in a. This basically returns you a reference of the inner function func which is called by the last line a("function call").
The important point here is that though the function func2 is out of scope, the argument passed to it is still available in the memory.

Usage - Closures are sometime an alternative to making a Class when the number of methods you have is less.

Q. What are Decorators and when are they used?
A. Decorators in Python are a design pattern used to add higher level functionality to an existing object. Basically, a decorators takes another function as an argument and adds to the functionality without explicitly modifying it.
Let's study it in more details.
Decorators make use of Closure to add the higher level functionality. Let's modify our Closure example a bit:
def func2(func):
def inner(mystr):
print("Do something before the decorated function")
func(mystr)
print("Do something after the decorated function")
return inner

def print_something(mystr):
print(mystr)
print_something = func2(print_something) #closure
print_something ("calling")

Output:
ankit@MYPC $ python test.py
Do something before the decorated function
calling
Do something after the decorated function

Here we have wrapped the main function using func2. So, while the function name print_something remains the same, its functionality has been decorated by the code inside the inner function. You can do something before or after the actual function is called.
Python comes with an easy way do add a decorator to a function by using the ampersand (@). The previous code can be modified to:
def func2(func):
def inner(mystr):
print("Do something before the decorated function")
func(mystr)
print("Do something after the decorated function")
return inner

@func2
def print_something(mystr):
print(mystr)

print_something ("calling")

Q. What is the difference between classmethod and staticmethod

Q. What all can you import from a module? Example - Class, method, variable?

Q. Is it possible to use None, True, int as dictionary keys?

Q.When is the copy module used in Python

Q. What are some of the useful methods of the Collections module

Q. Explain the working of lambda, map, filter and reduce

Q. What is the difference between sort and sorted
A. "sort" is a method available for a List type object.
>>> b = [4,2,5,7,4,2]
>>> b.sort()
>>> b
[2, 2, 4, 4, 5, 7]

"sorted" on the other hand is an in-built method that takes list as an argument.
>>> b = [4,2,5,7,4,2]
>>> sorted(b)
[2, 2, 4, 4, 5, 7]

The difference as you can see is that the sort method modifies the original list itself whereas sorted returns a copy of the sorted list.

Q. How do you sort a list values based on the attributes of the object. For example, sort the below list based on the dictionary values.
a = [{1:3},{2:5},{3:2},{4:1}]
A. sort and sorted, both have a "key" attribute that can be used to provide an attribute of the list object as the value for sorting. To sort the list given in the question, here is how to do it:
>>> sorted(a,key=lambda x:list(x.values())[0])
[{4: 1}, {3: 2}, {1: 3}, {2: 5}]
>>> a.sort(key=lambda x:list(x.values())[0])
>>> a
[{4: 1}, {3: 2}, {1: 3}, {2: 5}]


Explanation - We need to be able to access the values of each of the dictionary entry in the list. To do so, we make use of the lambda function. The function gets us the dict_value of a particular dictionary and then we typecast it to a list to get the integer value.
>>> a[1].values()
dict_values([5])
>>> list(a[1].values())[0]
5



Comments

No responses found. Be the first to comment...


  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email:
    -