Top 40 Python Interview Questions & Answers

17 mins read

Table of Contents

In this, top 40 Python Interview Questions & Answers, we will cover the following:

  • Most asked Python questions with answers.
  • We will provide the details with examples to make it more understandable.
  • Fast lookup before the interview.
  • Python Interview Questions for Freshers and Experienced.
  • Python OOPS Interview Questions
  • Python Libraries Interview Questions
  • Python Programming Examples

Python Introduction

  • Python was released on February 20, 1991, and developed by Guido van Rossum.
  • It is a widely used and most loved programming language.
  • Python is interpreted in nature, which provides flexibility in incorporating dynamic semantics. This makes it easy for developers to learn Python.
  • Python also supports object-oriented programming and is most commonly used to perform general-purpose programming.
  • It can be used to develop any kind of application.
  • Reduce the cost of program maintenance.
  • Has many libraries, so we don’t have to write everything from the initial.
  • High level of data structure.
  • Huge community of developers.

We will try to answer common questions also like:

Q. What are good Python interview questions?
Q. How to prepare Python for the interview?
Q. What are the basic Python questions?
Q. Can you talk a little about your experience in Python?
Q. How do I prepare for a Python interview?
Q. How do you stand out in a Python coding interview?


Python Interview Questions for Freshers

1. What is a dynamically typed language?

Python is an interpreted language that executes each statement line by line and thus type checking is done on the fly during execution. Hence, Python is a dynamically typed language.

In a strongly typed language, such as Python, “1” + 2 will result in a type error since these languages don’t allow for “type-coercion” (implicit conversion of data types). On the other hand, a weakly typed language, such as JavaScript, will output “12” as a result.

Type-checking can be done in two stages –

  • Static – Data Types are checked before execution.
  • Dynamic – Data Types are checked during execution.

For example:

a = 10
b = 10.50
c = "Welcome"
print(a)
print(b)
print(c)
# ----output------:
# 10
# 10.50
# "Welcome" 

In the above example, we haven’t defined the variable ‘a’ as an integer, ‘b’ as float, and ‘c as a string. Instead of that, we are directly assigning respective values. At the time of execution, the variable types get defined automatically depending on the value it contains.

2. What is PEP 8, and why is it important?

PEP denotes Python Enhancement Proposal. It’s a collection of guidelines for formatting Python code for maximum readability. Here is complete detail: PEP8

3. What is Scope in Python?

In Python, scope refers to the region or block of code where a variable, function, or object is defined and can be accessed. Python has two types of scope:

Every object in Python functions within a scope. A scope is a block of code where an object in Python remains relevant. Namespaces uniquely identify all the objects inside a program. However, these namespaces also have a scope defined for them where you could use their objects without any prefixes. A few examples of scope created during code execution in Python are as follows:

  • local scope refers to the local objects available in the current function.
  • global scope refers to the objects available throughout the code execution since their inception.
  • module-level scope refers to the global objects of the current module accessible in the program.
  • An outermost scope refers to all the built-in names callable in the program. The objects in this scope are searched last to find the name referenced.

Note: Local scope objects can be synced with global scope objects using keywords such as global.

It’s important to keep in mind the scope of variables and objects in Python, as it can affect the behavior of your program. For example, if a variable is defined in the global scope and also used within a function, and the function modifies the value of the variable, the change will be reflected globally in the program.

4. What are lists and tuples? What is the key difference between the two?

Lists and Tuples are sequence data types that can store a collection of objects in Python. The objects stored in both sequences can have different data types. Lists are represented with square brackets['Mr. Xyz', 6, 0.19], while tuples are represented with parentheses ('Mr. Xyz', 5, 0.97).

SR.NO.LISTTUPLE
1Lists are mutableTuples are immutable
2The implication of iterations is Time-consumingThe implication of iterations is comparatively Faster
3The list is better for performing operations, such as insertion and deletion.Unexpected changes and errors are more likely to occur
4Lists consume more memoryTuple consumes less memory as compared to the list
5Lists have several built-in methodsTuple does not have many built-in methods.

Test both for memory efficient:

import sys
a_list = []
a_tuple = ()
a_list = ["Djha", "For", "Blog"]
a_tuple = ("Djha", "For", "Blog")
print(sys.getsizeof(a_list))
print(sys.getsizeof(a_tuple))
#------------------------------------------
# Output:
# 120
# 64

Test immutable and mutable:

my_tuple = ('xyz', 6, 5, 0.97)
my_list = ['xyz', 6, 5, 0.97]
print(my_tuple[0])     # output => 'xyz'
print(my_list[0])     # output => 'xyz'
my_tuple[0] = 'abc'    # modifying tuple => throws an error
my_list[0] = 'abc'    # modifying list => list modified
print(my_tuple[0])     # output => 'xyz'
print(my_list[0])     # output => 'abc'

5. What are Python Keywords?

There are 33 keywords in Python:

andasassertbreak
classcontinuedefdel
elifelseexceptFalse
finallyforfromglobal
ifimportinis
lambdaNonenonlocalnot
orpassraisereturn
Truetrywhilewith
yield

6. What are the common built-in data types in Python?

There are different built-in data types in Python. However, it doesn’t require data types to be defined explicitly during variable declarations in Python. The type errors are likely to occur if the knowledge of data types and their compatibility with each other are mismatched.

Python provides type() and isinstance() functions to check the type of variables. These data types can be grouped into categories:

  • None Type:
    None the keyword represents the null values. Boolean equality operation can be performed using these NoneType objects.
Class NameDescription
NoneTypeRepresents NULL values in Python.
  • Numeric Types:
    integers, floating-point numbers, and complex numbers.
  • Additionally, booleans are a sub-type of integers.
Class NameDescription
intComplex numbers in the form (A + Bj) and have attributes: real and imag
floatLiterals containing decimal values and/or exponent signs as floating-point numbers
complexComplex numbers in the form (A + Bj) and have attributes: real and imag
boolBoolean value (True or False).
  • Sequence Types:
    As per Python Documents, there are three basic Sequence Types – lists, tuples, and range objects. Sequence types have the in and not in operators for traversing their elements. These operators share the same priority as the comparison operations.
Class NameDescription
listMutable sequence used to store collection of items.
tupleImmutable sequence used to store collection of items.
rangeRepresents an immutable sequence of numbers generated during execution.
strThe Immutable sequence of Unicode code points to store textual data.

Note: The standard library also includes additional types of processing:
1. Binary data such as bytearray bytes memoryview, and
2. Text strings such as str.

  • Mapping Types:

A mapping object can map hashable values to random objects in Python. Mapping objects are mutable and there is currently only one standard mapping type, the dictionary.

Class Name Description
dictStores comma-separated list of key: value pairs
  • Set Types:
    Currently, Python has two built-in set types – set and frozensetset type is mutable and supports methods like add() and remove()frozenset type is immutable and can’t be modified after creation.
Class NameDescription
setThe Mutable unordered collection of distinct hashable objects.
frozensetImmutable collection of distinct hashable objects.

Note: set is mutable and thus cannot be used as a key for a dictionary. On the other hand, frozenset is immutable and thus, hashable, and can be used as a dictionary key or as an element of another set.

  • Modules:
    The module is an additional built-in type supported by the Python Interpreter. It supports one special operation, i.e., attribute access: mymod.myobj, where mymod is a module and myobj references a name defined in the symbol table. The module’s symbol table resides in a special attribute of the module __dict__, but direct assignment to this module is neither possible nor recommended.
  • Callable Types:
    Callable types are the types to which a function call can be applied. They can be user-defined functions, instance methods, generator functions, and other built-in functions, methods, and classes.
    Refer to the documentation at docs.python.org for a detailed view of the callable types.

7. What is __init__ in python?

__init__ is just like a constructor method in Python. It is automatically called to allocate memory when a new object or instance is created. All classes have a __init__ method associated with them. It helps in distinguishing methods and attributes of a class from local variables.

class Employee:
   def __init__(self, fname, lname, age, section):
       self.firstname = fname
       self.lastname = lname
       self.age = age
       self.section = section
emp = Employee("John", "borthwick", 22, "A2")

8. How can we make a Python Script executable on Unix?

We can create a .py script file that must begin with #!/usr/bin/env python

9. What are packages and modules in Python?

Modules, in general, are simply Python files with a .py extension and can have a set of functions, classes, or variables defined and implemented. They can be imported and initialized once using the import statement. If partial functionality is needed, import the requisite classes or functions using from foo import bar.

Packages allow for hierarchical structuring of the module namespace using dot notation. As modules help avoid clashes between global variable names, similarly, packages help avoid clashes between module names.
Creating a package is easy since it makes use of the system’s inherent file structure. So just collect the modules into a folder and there you have it, the folder name as the package name. Importing a module or its contents from this package requires the package name as a prefix to the module name, joined by a dot.

Note: You can technically import the package as well, but it doesn’t import the modules within the package to the local namespace, thus, it is practically useless.

10. What is the use of self in Python?

Self is used to represent the instance of the class, it’s not a keyword in Python. With this, we can access the attributes and methods of the class in python. It binds the attributes with the given arguments.

def __init__(self fname, lname, age, section):
    self.firstname = fname
    self.lastname = lname
    self.age = age
    self.section = section

11. What are global, protected, and private attributes in Python?

Python uses ‘_’ symbol to determine the access control for a specific data member or a member function of a class. Access specifiers in Python have an important role to play in securing data from unauthorized access and in preventing it from being exploited.
A Class in Python has three types of access modifiers:

  • Public Access Modifier
  • Protected Access Modifier
  • Private Access Modifier

Public Access Modifier: Accessible from any part of the program. All data members and member functions of a class are public by default.

class Employee:
     # constructor
     def __init__(self, name, age):
           # public data members
           self.name = name
           self.age = age
 
     # public member function     
     def displayAge(self):
           # accessing public data member
           print("Age: ", self.age)
 
# creating object of the class
obj = Employee("ABC", 20)
 
# accessing public data member
print("Name: ", obj.name)
 
# calling public member function of the class
obj.displayAge()

Protected Access Modifier: The members of a class that are declared protected are only accessible to a class derived from it. Data members of a class are declared protected by adding a single underscore ‘_’ symbol before the data member of that class. 

# super class
class Student:
     # protected data members
     _name = None
     _roll = None
     _branch = None
    
     # constructor
     def __init__(self, name, roll, branch): 
          self._name = name
          self._roll = roll
          self._branch = branch
    
     # protected member function  
     def _displayRollAndBranch(self):
 
          # accessing protected data members
          print("Roll: ", self._roll)
          print("Branch: ", self._branch)
 
 
# derived class
class Derived(Student):
 
       # constructor
       def __init__(self, name, roll, branch):
                Student.__init__(self, name, roll, branch)
         
       # public member function
       def displayDetails(self):
                   
                 # accessing protected data members of super class
                print("Name: ", self._name)
                   
                 # accessing protected member functions of super class
                self._displayRollAndBranch()
 
# creating objects of the derived class       
obj = Derived("ABC", 1706223, "Hello World")
 
# calling public member functions of the class
obj.displayDetails()
#-----------------------------------------------------------------
# Output:
# Name:  ABC
# Roll:  1706223
# Branch:  Hello World

Private Access Modifier: The members of a class that are declared private are accessible within the class only, private access modifier is the most secure access modifier. Data members of a class are declared private by adding a double underscore ‘__’ symbol before the data member of that class. 

class Employee:
    
     # private members
     __name = None
     __roll = None
     __branch = None
 
     # constructor
     def __init__(self, name, roll, branch): 
          self.__name = name
          self.__roll = roll
          self.__branch = branch
 
     # private member function 
     def __displayDetails(self):
           
           # accessing private data members
           print("Name: ", self.__name)
           print("Roll: ", self.__roll)
           print("Branch: ", self.__branch)
    
     # public member function
     def accessPrivateFunction(self):
            
           # accessing private member function
           self.__displayDetails() 
 
# creating object   
obj = Employee("ABC", 1706223, "Hello World")
 
# calling public member function of the class
obj.accessPrivateFunction()

In the above program, __name, __roll and __branch are private members, __displayDetails() method is a private member function (these can only be accessed within the class) and accessPrivateFunction() method is a public member function of the class Employee which can be accessed from anywhere within the program.

12 What is break, continue, and pass in Python?

BreakThe break statement terminates the loop immediately and the control flows to the statement after the body of the loop.
ContinueThe continue statement terminates the current iteration of the statement, skips the rest of the code in the current iteration and the control flows to the next iteration of the loop.
PassAs explained above, the pass keyword in Python is generally used to fill up empty blocks and it is similar to an empty statement represented by a semi-colon in languages such as Java, C++, Javascript, etc.
list_pat = [1, 3, 2, 1, 2, 3, 1, 0, 1, 3]
for p in list_pat:
   pass
   if (p == 0):
       current = p
       break
   elif (p % 2 == 0):
       continue
   print(p)    # output => 1 3 1 3 1
print(current)    # output => 0

13. What is the difference between Python Arrays and lists?

  • Arrays in Python can only contain elements of the same data types, i.e. data type of the array should be homogeneous. It is a thin wrapper around C language arrays and consumes far less memory than lists.
  • Lists in Python can contain elements of different data types, i.e., data types of lists can be heterogeneous. It has the disadvantage of consuming large memory.
import array
a = array.array('i', [1, 2, 3])
for i in a:
    print(i, end=' ')    #OUTPUT: 1 2 3
a = array.array('i', [1, 2, 'string'])    #OUTPUT: TypeError: an integer is required (got type str)
a = [1, 2, 'string']
for i in a:
   print(i, end=' ')    #OUTPUT: 1 2 string

14. What is slicing in Python

Syntax: slice(start, stop, step)

Parameters: 

  • start: Starting index where the slicing of object starts.
  • stop: Ending index where the slicing of object stops.
  • step: It is an optional argument that determines the increment between each index for slicing.

Return Type: Returns a sliced object containing elements in the given range only. 

l = ['a', 'b', 'c', 'd', 'e', 'f']
slice_obj = slice(-2, -6, -1)
print("list slicing:", l[slice_obj])
 
# string -ve index slicing
s = "djha"
slice_obj = slice(-1)
print("string slicing:", s[slice_obj])
 
# tuple -ve index slicing
t = (1, 3, 5, 7, 9)
slice_obj = slice(-1, -3, -1)
print("tuple slicing:", t[slice_obj])
OUTPUT:
list slicing: ['e', 'd', 'c', 'b']
string slicing: djh
tuple slicing: (9, 7)

Python Interview Questions for Experienced

15. What is Scope Resolution in Python?

Sometimes objects within the same scope have the same name but function differently. In such cases, scope resolution comes into play in Python automatically.

Scope resolution LEGB rule In Python: The LEGB rule is used to decide the order in which the namespaces are to be searched for scope resolution.
The scopes are listed below in terms of hierarchy:

  • Local(L): Defined inside function/class
  • Enclosed(E): Defined inside enclosing functions (Nested function concept)
  • Global(G): Defined at the uppermost level
  • Built-in(B): Reserved names in Python built-in modules
Python Interview Questions and Answers

Local Scope in Python

Local scope refers to variables defined in the current function. A function will first look up a variable name in its local scope. Only if it does not find it there, the outer scopes are checked. 

# Local Scope
pi = 'global variable'
def inner():
    pi = 'inner variable'
    print(pi)
  
inner()

Output:

inner variable

Local and Global Scopes in Python

If a variable is not defined in the local scope, it is checked for in the higher scope, in this case, the global scope.

# Global Scope
pi = 'global variable'
def inner():
	pi = 'inner variable'
	print(pi)
inner()
print(pi)

Output:

inner variable
global variable

Local, Enclosed, and Global Scopes in Python

# Enclosed Scope
pi = 'global variable'
def outer():
	pi = 'outer variable'
	def inner():
		# pi = 'inner variable'
		nonlocal pi
		print(pi)
	inner()
outer()
print(pi)

Output:

outer variable
global variable

Local, Enclosed, Global, and Built-in Scopes

# Built-in Scope
from math import pi
# pi = 'global pi variable'
def outer():
	# pi = 'outer pi variable'
	def inner():
		# pi = 'inner pi variable'
		print(pi)
	inner()
outer()

Output:

3.141592653589793

16. What are Dict and List comprehensions?

Python comprehensions are syntactic sugar constructs that help build altered and filtered lists, dictionaries, or sets from a given list, dictionary, or set. Comprehensions save a lot of time and code that might be considerably more verbose (containing more lines of code).

my_list = [2, 3, 4, 5, 6]
squared_list = [x**2 for x in my_list]    # list comprehension
# output => [4, 6, 8, 10, 12]
squared_dict = {x:x**2 for x in my_list}    # dict comprehension
# output => {2: 4, 3: 9, 4: 16, 5: 25, 6: 36}
my_list = [2, 3, 5, 7, 11]
squared_list = [x**2 for x in my_list if x%2 != 0]    # list comprehension
# output => [9, 25, 49, 121]
squared_dict = {x:x**2 for x in my_list if x%2 != 0}    # dict comprehension
# output => {11: 121, 3: 9, 5: 25, 7: 49}
a = [1, 2, 3]
b = [7, 8, 9]
[(x + y) for (x, y) in zip(a, b)]  # parallel iterators
# output => [8, 10, 12]
[(x, y) for x in a for y in b]    # nested iterators
# output => [(1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (2, 9), (3, 7), (3, 8), (3, 9)]
my_list = [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
flattened = [x for temp in my_list for x in temp]
# output => [10, 20, 30, 40, 50, 60, 70, 80, 90]

We have a dedicated article on this topic here

17. What are decorators in Python?

Decorators in Python are essential functions that add functionality to an existing function in Python without changing the structure of the function itself. They are represented by the @decorator_name in Python. Called in a bottom-up fashion.

# decorator function to convert to lowercase
def lower_decorator(function):
   def wrapper():
       func = function()
       string_lower = func.lower()
       return string_lower
   return wrapper
# decorator function to split words
def splitter_decorator(function):
   def wrapper():
       func = function()
       string_split = func.split()
       return string_split
   return wrapper
@splitter_decorator # this is executed next
@lower_decorator # this is executed first
def hello():
   return 'Hello World'
hello()   
# output => [ 'hello' , 'world' ]

Decorators are remarkable in that they not only enhance the output of a method with additional functionality but also can receive arguments for functions and modify them before they are passed to the function. This is made possible by the presence of the inner nested function, known as the “wrapper” function, which plays a crucial role in enforcing encapsulation and keeping itself concealed from the global scope.

# decorator function to capitalize
def names_decorator(function):
   def wrapper(arg1, arg2):
       arg1 = arg1.capitalize()
       arg2 = arg2.capitalize()
       str_hello = function(arg1, arg2)
       return str_hello
   return wrapper
@names_decorator
def say_hello(name1, name2):
   return 'Hello ' + name1 + '! Hello ' + name2 + '!'
say_hello('John', 'Kiya')   
# output => 'Hello John! Hello Kiya!'

18. What is Shallow and Deep copy in Python?

In Python, Assignment statements do not copy objects, they create bindings between a target and an object. When we use the = operator, It only creates a new variable that shares the reference of the original object. In order to create “real copies” or “clones” of these objects.

Shallow Copy is a bit-wise copy of an object. The copied object created has an exact copy of the values in the original object. If either of the values is a reference to other objects, just the reference addresses for the same are copied.
Deep Copy copies all values recursively from the source to the target object, i.e. it even duplicates the objects referenced by the source object.

from copy import copy, deepcopy
list_1 = [1, 2, [3, 5], 4]
## shallow copy
list_2 = copy(list_1) 
list_2[3] = 7
list_2[2].append(6)
list_2    # output => [1, 2, [3, 5, 6], 7]
list_1    # output => [1, 2, [3, 5, 6], 4]
## deep copy
list_3 = deepcopy(list_1)
list_3[3] = 8
list_3[2].append(7)
list_3    # output => [1, 2, [3, 5, 6, 7], 8]
list_1    # output => [1, 2, [3, 5, 6], 4]

shallow copy creates a new compound object and then references the objects contained in the original within it, which means it constructs a new collection object and then populates it with references to the child objects found in the original. The copying process does not recurse and therefore won’t create copies of the child objects themselves. In the case of shallow copy, a reference of an object is copied into another object. It means that any changes made to a copy of an object do reflect in the original object. In Python, this is implemented using the “copy()” function. 

# importing "copy" for copy operations
import copy
 
# initializing list 1
li1 = [1, 2, [3,5], 4]
 
# using copy to shallow copy
li2 = copy.copy(li1)
 
# original elements of list
print ("The original elements before shallow copying")
for i in range(0,len(li1)):
    print (li1[i],end=" ")
 
print("\r")
 
# adding and element to new list
li2[2][0] = 7
 
# checking if change is reflected
print ("The original elements after shallow copying")
for i in range(0,len( li1)):
    print (li1[i],end=" ")

Output:

The original elements before shallow copying
1 2 [3, 5] 4 
The original elements after shallow copying
1 2 [7, 5] 4 

A deep copy creates a new compound object before inserting copies of the items found in the original into it in a recursive manner. It means first constructing a new collection object and then recursively populating it with copies of the child objects found in the original. In the case of deep copy, a copy of the object is copied into another object. It means that any changes made to a copy of the object do not reflect in the original object. 

# importing "copy" for copy operations
import copy
# initializing list 1
li1 = [1, 2, [3,5], 4]
# using deepcopy to deep copy
li2 = copy.deepcopy(li1)
# original elements of list
print ("The original elements before deep copying")
for i in range(0,len(li1)):
	print (li1[i],end=" ")
print("\r")
# adding and element to new list
li2[2][0] = 7
# Change is reflected in l2
print ("The new list of elements after deep copying ")
for i in range(0,len( li1)):
	print (li2[i],end=" ")
print("\r")
# Change is NOT reflected in original list
# as it is a deep copy
print ("The original elements after deep copying")
for i in range(0,len( li1)):
	print (li1[i],end=" ")

Output:

The original elements before deep copying
1 2 [3, 5] 4 
The new list of elements after deep copying 
1 2 [7, 5] 4 
The original elements after deep copying
1 2 [3, 5] 4 

18. What is pickling and unpickling?

In Python, we have – serialization, and serializing an object refers to transforming it into a format that can be stored, to be able to deserialize it, later on to obtain the original object. For this, in Python, we have a pickle module.

Pickling:

  • Pickling is the name of the serialization process in Python. Any object in Python can be serialized into a byte stream and dumped as a file in the memory. The process of pickling is compact but pickle objects can be compressed further. Moreover, pickle keeps track of the objects it has serialized and the serialization is portable across versions.
  • The function used for the above process is pickle.dump().

Unpickling:

  • Unpickling is the complete inverse of pickling. It deserializes the byte stream to recreate the objects stored in the file and loads the object to memory.
  • The function used for the above process is pickle.load().
image 3

19. How is memory managed in Python?

Memory is managed by Python Memory Manager. The memory allocated by the manager is in the form of a private heap space dedicated to Python. Memory management in Python is handled automatically by the interpreter. Python uses a garbage collector to manage memory automatically so that developers don’t have to worry about allocating and freeing memory manually.

Garbage Collection:

It is a process in which the interpreter frees up the memory when not in use to make it available for other objects. Assume a case where no reference is pointing to an object in memory i.e. it is not in use so, the virtual machine has a garbage collector that automatically deletes that object from the heap memory.

Reference Counting:

Python uses reference counting to keep track of objects in memory. Every object in Python has a reference count, which is the number of references pointing to that object.

When an object is created, its reference count is set to 1. If a reference to the object is created, the reference count is incremented by 1.

When a reference to the object is deleted, the reference count is decremented by 1. When the reference count of an object reaches 0, it is no longer in use and its memory is freed.

x = 20
y = x
  
if id(x) == id(y):
    print("x and y refer to the same object")

Output:

x and y refer to the same object
Screenshot 2023 02 18 at 11.46.04 PM

Let’s change the value of x and see the changes in memory.

x = 20
y = x
x += 1
if id(x) != id(y):
	print("x and y do not refer to the same object")

Output:

x and y do not refer to the same object

Now x refer to a new object x and the link between x and 20 disconnected, but y still refer to 20.

image 4

There are two parts of memory:

  • Stack memory: It is the memory that is only needed inside a particular function or method call. When a function is called, it is added to the program’s call stack. Any local memory assignments such as variable initializations inside the particular functions are stored temporarily on the function call stack, where it is deleted once the function returns, and the call stack moves on to the next task. This allocation onto a contiguous block of memory is handled by the compiler using predefined routines, and developers do not need to worry about it.
  • Heap memory: The variables that are needed outside of method or function calls or are shared within multiple functions globally are stored in Heap memory. The name heap has nothing to do with the heap data structure.

The methods/method calls and the references are stored in stack memory and all the values objects are stored in a private heap.

# This memory for 10 integers  
# is allocated on heap.  
a = [0]*10
def func(): 
        
    # All these variables get memory  
    # allocated on stack  
    a = 20
    b = [] 
    c = ""

20. What is lambda in Python? Why is it used?

In Python, the lambda is an anonymous function that can accept any number of arguments, but can only have a single expression. It is generally used in situations requiring an anonymous function for a short period.

Lambda functions can be used in either of the two ways

  1. Assigning lambda functions to a variable:
mul = lambda a, b : a * b
print(mul(2, 10))    # output => 20

2. Wrapping lambda functions inside another function:

def myWrapper(n):
 return lambda a : a * n
mulFive = myWrapper(10)
print(mulFive(2))    # output => 20

21. What are generators in Python?

It is a function that returns an iterable collection of items, one at a time, in a set manner. Generators, in general, are used to create iterators with a different approach. It uses yield keyword rather than return to return a generator object. If the body of a def contains yield, the function automatically becomes a generator function.
Example:

# A generator function that yields 1, 2 and 3 one by one
def testGeneratorFunc():
    yield 1           
    yield 2           
    yield 3           
  
# Check above generator function
for value in testGeneratorFunc():
    print(value)

Output:

1
2
3

Another example:

# A simple generator for Fibonacci Numbers
def fib(limit):
     
    # Initialize first two Fibonacci Numbers
    a, b = 0, 1
 
    # One by one yield next Fibonacci Number
    while a < limit:
        yield a
        a, b = b, a + b
 
# Create a generator object
x = fib(5)
 
# Iterating over the generator object using next
print(next(x)) # In Python 3, __next__()
print(next(x))
print(next(x))
print(next(x))
print(next(x))
 
# Iterating over the generator object using for
# in loop.
print("\nUsing for in loop")
for i in fib(5):
    print(i)

Output:

0
1
1
2
3

Using for in loop
0
1
1
2
3

22. What is the difference between .py and .pyc files?

  • .py files contain the source code of a program. Whereas, .pyc file contains the bytecode of your program. We get bytecode after compilation of .py file (source code). .pyc files are not created for all the files that you run. It is only created for the files that you import.
  • Before executing a python program python interpreter checks for the compiled files. If the file is present, the virtual machine executes it. If not found, it checks for .py file. If found, compiles it to .pyc file and then python virtual machine executes it.
  • Having .pyc file saves you the compilation time.

23. How are arguments passed by value or by reference in Python?

  • Pass by value: The copy of the actual object is passed. Changing the value of the copy of the object will not change the value of the original object.
  • Pass by reference: Reference to the actual object is passed. Changing the value of the new object will change the value of the original object.

In Python, arguments are passed by reference, i.e., reference to the actual object is passed.

def appendNumber(arr):
   arr.append(4)
arr = [1, 2, 3]
print(arr)  #Output: => [1, 2, 3]
appendNumber(arr)
print(arr)  #Output: => [1, 2, 3, 4]

24. How to delete a file in Python?

import os
# A file.txt is there on same location
os.remove("file.txt")
print("File Removed!")

25. What is *args and **kwargs mean in python?

*args:

  • *args is a special syntax used in the function definition to pass variable-length arguments.
  • “*” means variable length, and “args” is the name used by convention. You can use any other.
def multiply(a, b, *argv):
   mul = a * b
   for num in argv:
       mul *= num
   return mul
print(multiply(1, 2, 3, 4, 5)) #output: 120

**kwargs

  • **kwargs is a special syntax used in the function definition to pass variable-length keyworded arguments.
  • Here, also, “kwargs” is used just by convention. You can use any other name.
  • Keyworded argument means a variable that has a name when passed to a function.
  • It is a dictionary of the variable names and its value.
def tellArguments(**kwargs):
   for key, value in kwargs.items():
       print(key + ": " + value)
tellArguments(arg1 = "argument 1", arg2 = "argument 2", arg3 = "argument 3")
#output:
# arg1: argument 1
# arg2: argument 2
# arg3: argument 3

Python OOPS Interview Questions

26. What is class in Python?

Since Python is an object-oriented programming language, the concept of class in Python is the same as in other OOPS programming languages.

A class is a code template for creating objects. Objects have member variables and have behavior associated with them. In Python, a class is created by the keyword class.

An object is created using the constructor of the class. This object will then be called the instance of the class.

Consider the following code block:

class Employee:
   def __init__(self, emp_name):
       self.emp_name = emp_name
       
   def introduce(self):
       print("Hello I am " + self.emp_name)
       
# create an object of Employee class
emp_1 = Employee("Mr John")
print(emp_1.emp_name)    #print employee name
emp_1.introduce()        #introduce the employee

In the above example, “Employee” is the class, and “emp_1” is an instance of the class “Employee”.

27. What is inheritance in Python? Explain it with an example of all inheritance in Python.

Inheritance gives the power to a class to inherit the attributes and methods of another class. It increases code reusability and helps the developer to maintain applications without redundant code. The class inheriting from another class is a child class also called a derived class. The class from which a child class derives, the members, are called parent class or superclass.

The different inheritance in Python:

Single Inheritance: Child class derives From members of only one parent class.

image 5
# Parent class
class ParentClass:
    def par_func(self):
         print("I am parent class function")
# Child class
class ChildClass(ParentClass):
    def child_func(self):
         print("I am child class function")
# Driver code
obj = ChildClass()
obj.par_func()
obj.child_func()

Multi-level Inheritance: The members of the parent class, A, are inherited by a child class which is then inherited by another child class, B. The features of the base class and the derived class are further inherited into the new derived class, C. Here, A is the grandfather class of class C.

image 6
# Parent class
class A:
   def __init__(self, a_name):
       self.a_name = a_name
   
# Intermediate class
class B(A):
   def __init__(self, b_name, a_name):
       self.b_name = b_name
       # invoke constructor of class A
       A.__init__(self, a_name)
# Child class
class C(B):
   def __init__(self,c_name, b_name, a_name):
       self.c_name = c_name
       # invoke constructor of class B
       B.__init__(self, b_name, a_name)
       
   def display_names(self):
       print("A name : ", self.a_name)
       print("B name : ", self.b_name)
       print("C name : ", self.c_name)
#  Driver code
obj = C('child', 'intermediate', 'parent')
print(obj.a_name)
obj.display_names()

Multiple Inheritance: When one child class derives members from more than one parent class, all the features of parent classes are inherited in the child class and this is called multiple inheritance.

image 7
# Parent class1
class ParentA:
   def parentA_func(self):
       print("Hi I am first Parent")
# Parent class2
class ParentB:
   def parentB_func(self):
       print("Hi I am second Parent")
# Child class
class Child(ParentA, ParentB):
   def child_func(self):
       self.parentA_func()
       self.parentB_func()
# Driver's code
obj = Child()
obj.child_func()

Hierarchical Inheritance: When a parent class is derived by more than one child class, it is called hierarchical inheritance.

image 9
# Base class
class A:
     def a_func(self):
         print("I am from the parent class.")
# 1st Derived class
class B(A):
     def b_func(self):
         print("I am from the first child.")
# 2nd Derived class
class C(A):
     def c_func(self):
         print("I am from the second child.")
 
# Driver's code
obj1 = B()
obj2 = C()
obj1.a_func()
obj1.b_func()    #child 1 method
obj2.a_func()
obj2.c_func()    #child 2 method

28. Is it possible to call the parent class without its instance creation?

Yes, it is possible if the base class is instantiated by other child classes or if the base class is a static method.

29. What is multi-threading in Python? What is GIL and how to increase CPU utilization?

A thread is a separate flow of execution. Multi-threading allows us to execute multiple blocks of code concurrently. Example of multithreading in Python:

from threading import Thread
import time
class MyThread(Thread):
    def __init__(self):
        super().__init__()
    
    def run(self):
        print("A thread is running")
        time.sleep(5)
        print("A tread is exited")
mt = MyThread()
mt.start()  # This will call run above function
# threading.active.count() : Used to count running threads

GIL (Global Interpreter Lock): It allows threads to use only one core of CPU to limit CPU utilization.

Process in Python: If we have a program that needs more CPU used, then we can use the process from the multiprocessing Python library. It allows us to use 100% CPU utilization.

from multiprocessing import Process
def working_process():
    while True:
        pass
proc = Process(target = working_process)
proc.start()
proc.terminate()
proc.close()
# As per above code it's important to terminate and close the tread.

30. What is Singleton in Python?

Singleton is a way to create only one actual instance of a class. However, if we create multiple instances from that class, all the instances will point to the same instance of that singleton class.

class Singleton:
    __instance = None
    @staticmethod
    def getInstance():
        if Singleton.__instance == None:
            Singleton()
        return Singleton.__instance
    def __init__(self):
        if Singleton.__instance != None:
            raise Exception("Singleton exists already")
        Singleton.__instance = self
s1 = Singleton.getInstance()
s2 = Singleton.getInstance()
s1.x = 5
print(s2.x)
# both s1 and s2 pints to same single instance of Singleton class

31. What are closures in Python?

Closure is a technique by which data gets attached to the code.
These are function objects that remember values in enclosing scope even if they are not present in the memory.
Must have: 1. A nested function and 2. A nested function should call in an outer function.
For example:

def outer():
    def inner():
        x = 20
        return x
    return inner
inner = outer()  # Garbage all memory at this point, but on next line we get value of x
print(inner())   # => 20

Python Libraries Interview Questions

32. How can you generate random numbers?

# First with the help of random() method 
# from random library
import random
print(random.random())
# Second with randrange() method of random library
# Syntax: randrange(beginning, end, step)
print(random.randrange(5,100,2))

33. How to check if all characters in the given string are alphanumeric?

"abdc1321".isalnum() #Output: True
"xyz@123$".isalnum() #Output: False
# Another way is to use match() method 
# from the re (regex) module as shown:
import re
print(bool(re.match('[A-Za-z0-9]+$','abdc1321'))) # Output: True
print(bool(re.match('[A-Za-z0-9]+$','xyz@123$'))) # Output: False

34. What are some of the most commonly used built-in modules in Python?

Here are a few common built-in modules:

  • os
  • math
  • sys
  • random
  • re
  • datetime
  • JSON

Python Programming Examples

Python coding interview questions

35. A program to take a sequence of numbers and check if all numbers are unique.

def check_distinct(data_list):
 if len(data_list) == len(set(data_list)):
   return True
 else:
   return False;
print(check_distinct([1, 6, 5, 8]))       # Prints True
print(check_distinct([2, 2, 5, 5, 7, 8])) # Prints False

36. A program to check and return the pairs of a given array A whose sum value is equal to a target value N

def pairs(arr, N):
   # hash set
   hash_set = set()
    
   for i in range(0, len(arr)):
       val = N-arr[i]
       if (val in hash_set):    #check if N-x is there in set, print the pair
           print("Pairs " + str(arr[i]) + ", " + str(val))
       hash_set.add(arr[i])
# Testing
arr = [1, 2, 40, 3, 9, 4]
N = 3
pairs(arr, N)  # output: Pairs 2, 1

37. Write a Program to match a string that has the letter ‘a’ followed by 4 to 8 ‘b’s.

import re
def match_text(txt_data):
    pattern = 'ab{4,8}'
    if re.search(pattern,  txt_data):    #search for pattern in txt_data
        return 'Match found'
    else:
        return('Match not found')
print(match_text("abc"))         #prints Match not found
print(match_text("aabbbbbc"))    #prints Match found

38. Write a program for counting the number of each character in a given text file.

import collections
import pprint
with open("sample_file.txt", 'r') as data:
   count_data = collections.Counter(data.read().upper())
   count_value = pprint.pformat(count_data)
print(count_value)

39. Write a Program to combine two different dictionaries and create a new dictionary. If you find the same keys, you can add the values of these same keys.

Here is code:

from collections import Counter
d1 = {'key1': 10, 'key2': 20, 'key3':30}
d2 = {'key1': 20, 'key2': 30, 'key4':40, 'key5': 50}
new_dict = Counter(d1) + Counter(d2)
print(new_dict)

We have a dedicated article for this here

40. Write a Program to add two integers without using the plus operator. The integers should be greater than 0.

def add_nums(number1, number2):
   while number2 != 0:
       data = number1 & number2
       number1 = number1 ^ number2
       number2 = data << 1
   return number1
print(add_nums(2, 10))

Conclusion

This article has provided a set of commonly asked interview questions for Python developers, which can be very helpful in preparing for interviews. Consistent practice with these questions, along with regular problem-solving sessions, can increase your chances of success in any Python-related job interview. The popularity of Python has grown significantly among developers in recent years, thanks to its ease of use and ability to handle complex computations. As a result, the demand for skilled Python developers continues to rise. However, it’s worth noting that being a Python developer has many advantages. In addition to a solid grasp of Python theory, proficiency in writing high-quality code is also essential. So, continue to learn and practice problems, and you’ll undoubtedly excel in interviews.

Best of luck for your next interview.

Back

Dharmendra is a blogger, author, Expert in IT Services and admin of DJTechnews. Good experience in software development. Love to write articles to share knowledge and experience with others. He has deep knowledge of multiple technologies and is always ready to explore new research and developments.

Leave a Comment

Stay Connected with us