In this guide, we’ll explore commonly asked Python interview questions, along with explanations to help you ace your next interview. Let’s dive into Python’s rich ecosystem and its real-world applications!
Table of Contents
Python was created by whom and when?
Python was created by Guido van Rossum and released in 1991.
What is the latest Python version?
The latest version of Python is 3.13.0, which was released on October 7, 2024. Always check the latest version at the time of your python interviews.
How do we do the casting of the variables?
x = str(3) # x will be '3'
y = int(3) # y will be 3
z = float(3) # z will be 3.0
PythonAre variables name case sensitive?
Variable names are case-sensitive.
a = 4
A = "Sally"
print(a) #4
print(A) #Sally
PythonDo we need to declare variables?
- Variables do not need to be declared of any particular type.
- A variable is created the moment you first assign a value to it, and you can even change the type after it has been set.
Assign values to multiple variables at once
x, y, z = "Orange", "Banana", "Cherry"
print(x) #Orange
print(y) #Banana
print(z) #Cherry
PythonAssign the same value to multiple variables at once
x = y = z = "Orange"
print(x) #Orange
print(y) #Orange
print(z) #Orange
PythonExplain the concept of unpacking a collection
If you have a collection of values in a list, tuple, etc. Python allows you to extract the values into variables. This is called unpacking.
fruits = ["apple", "banana", "cherry"]
x, y, z = fruits
print(x) #Orange
print(y) #Banana
print(z) #Cherry
PythonConcatenate of string and number?
- For numbers, the
+
operator works as a mathematical addition operator - For string, the
+
operator works concatenation operator - The mix of string and numbers will give an error
x = "Python "
y = "is "
z = "awesome"
print(x + y + z) #Python is awesome
x = 5
y = 10
print(x + y) #15
x = 5
y = "John"
print(x + y) #error
PythonWhat are the different variable scopes?
In Python, we can declare variables in three different scopes: local scope, global, and nonlocal scope.
Local Variables
When we declare variables inside a function, they are only accessible within the function and have a local scope.
def greet():
# local variable
message = 'Hello'
print('Local', message) # Hello
greet()
print(message) # this will give error
PythonGlobal Variables
In Python, a variable declared outside of the function or in a global scope is known as a global variable. This means that a global variable can be accessed inside or outside of the function.
# declare global variable
message = 'Hello'
def greet():
# declare local variable
print('Local', message) # Hello
greet()
print('Global', message) # Hello
PythonNonlocal Variables
In Python, the nonlocal keyword is used within nested functions to indicate that a variable is not local to the inner function, but rather belongs to an enclosing function’s scope.
It allows you to modify that variable in the outer function from within the inner function.
With nonlocal
# outside function
def outer():
message = 'backend'
# nested function
def inner():
# declare nonlocal variable
nonlocal message
message = 'mesh'
print("inner:", message) #inner: mesh
inner()
print("outer:", message) #outer: mesh
outer()
PythonWithout nonlocal
# outside function
def outer():
message = 'backend'
# nested function
def inner():
message = 'mesh'
print("inner:", message) #inner: mesh
inner()
print("outer:", message) #outer: backend
outer()
PythonWhat is the global keyword used for?
Variables that are created outside of a function are known as global variables.
x = "awesome"
def myfunc():
print("Python is " + x) #Python is awesome
myfunc()
PythonIf you create a variable with the same name inside a function, this variable will be local, and can only be used inside the function. The global variable with the same name will remain as it was, global and with the original value.
x = "awesome"
def myfunc():
x = "fantastic"
print("Python is " + x)
myfunc()
print("Python is " + x)
#Python is fantastic
#Python is awesome
PythonThe global Keyword
Variable x becomes global because of the global keyboard
def myfunc():
global x
x = "fantastic"
myfunc()
print("Python is " + x)
#Python is fantastic
PythonAlso, use the global
keyword if you want to change a global variable inside a function.
x = "awesome"
def myfunc():
global x
x = "fantastic"
myfunc()
print("Python is " + x)
#Python is fantastic
PythonRead about Nonlocal
What is id?
In Python, id is a built-in function used to retrieve the memory address of an object. Each object in Python has a unique identifier during its lifetime, and the id function provides this identifier. It is typically an integer that is unique to the object.
id(object)
x = 42
print(id(x)) # Unique identifier of the integer 42
a=b=c=4
print(id(a)) #9756320
print(id(b)) #9756320
print(id(c)) #9756320
a=2
b=3
print(id(a)) #9756256
print(id(b)) #9756288
print(id(c)) #9756320
PythonCommon mistake
#Works
print(id(56)) # 9757984
#Will Not work
id = 42 # Shadows the built-in 'id'
print(id(56)) # TypeError: 'int' object is not callable
PythonIn this case, Python cannot call the built-in id function because the local variable id has overshadowed it.
What are isinstance?
isinstance is a built-in Python function used to check whether an object belongs to a specific class or a tuple of classes. It is a reliable way to ensure that an object is of the desired type before performing certain operations on it.
isinstance(object, classinfo)
PythonParameters
- object: The object to check.
- classinfo: A class, type, or a tuple of classes and types to check against.
Return Value
- True if the object is an instance of the specified class or one of the classes in the tuple.
- False otherwise.
x = 10
print(isinstance(x, int)) # True (x is an instance of int)
print(isinstance(x, str)) # False (x is not a string)
PythonWhat is Type?
Returns the type of an object.
print(type(10)) #<class 'int'>
print(type('10')) #<class 'str'>
PythonWhat is issubclass?
Checks if a class is a subclass of another class.
class Animal: pass
class Dog(Animal): pass
print(issubclass(Dog, Animal)) # True
print(issubclass(Animal, Dog)) # False
PythonWhat are hasattr, getattr, setattr and delattr?
- hasattr: Checks if an object has a specific attribute.
- getattr: Retrieves the value of an attribute from an object. Allows a default value if the attribute does not exist.
- setattr: Sets an attribute on an object.
- delattr: Deletes an attribute from an object.
class MyClass:
def __init__(self):
self.value = 42
obj = MyClass()
print(hasattr(obj, 'value')) # True
print(hasattr(obj, 'name')) # False
print(getattr(obj, 'value')) # 42
print(getattr(obj, 'name', 0)) # 0 (default value)
setattr(obj, 'name','backendmesh')
print(obj.value) # backendmesh
delattr(obj, 'value')
# print(obj.value) # AttributeError: 'MyClass' object has no attribute 'value'
PythonWhat is vars?
Returns the __dict__ attribute of an object, showing its namespace.
class MyClass:
def __init__(self):
self.value = 42
obj = MyClass()
print(vars(obj)) # {'value': 42}
PythonWhat are built-in data types?
- Text Type: str
- Numeric Types: int, float, complex
- Sequence Types: list, tuple, range
- Mapping Type: dict
- Set Types: set, frozenset
- Boolean Type: bool
- Binary Types: bytes, bytearray, memoryview
- None Type: NoneType
Note
- Int, or integer, is a whole number, positive or negative, without decimals, of unlimited length.
- A frozenset in Python is an immutable version of a regular set
Example:
x = 1j
print(type(x)) #<class 'complex'>
x = range(6)
print(x) #range(0, 6)
print(type(x)) #<class 'range'>
PythonRange
The range() function defaults to increment the sequence by 1, however, it is possible to specify the increment value by adding a third parameter: range(2, 30, 3):
for x in range(2, 30, 3):
print(x)
Pythonfrozenset
A frozenset in Python is an immutable version of a regular set. Once created, its contents cannot be modified, which makes it hashable and usable as a key in a dictionary or as an element of another set.
x = frozenset({"apple", "banana", "cherry"})
print(x) #frozenset({'cherry', 'banana', 'apple'})
print(type(x)) #<class 'frozenset'>
PythonMultiline Strings
a = """Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua."""
print(a)
PythonStrings are Arrays
Like many other popular programming languages, strings in Python are arrays of bytes representing Unicode characters. However, Python does not have a character data type, a single character is simply a string with a length of 1.
Square brackets can be used to access elements of the string.
a = "Hello, World!"
print(a[1]) #e
PythonLooping Through a String
for x in "banana":
print(x)
PythonFinding a substring in a string
txt = "The best things in life are free!"
print("free" in txt) #True
PythonSlicing Strings
b = "Hello, World!"
print(b[2:5]) #llo
print(b[:5]) #Hello
print(b[2:]) #llo, World!
print(b[-5:-2]) #orl
PythonF-Strings
F-String was introduced in Python 3.6 and is now the preferred way of formatting strings. To specify a string as an f-string, simply put an f in front of the string literal, and add curly brackets {} as placeholders for variables and other operations.
age = 36
txt = f"My name is John, I am {age}"
print(txt) #My name is John, I am 36
PythonBoolean Values
In programming, you often need to know if an expression is True or False. You can evaluate any expression in Python, and get one of two answers, True or False.
print(10 > 9) #True
print(10 == 9) #False
print(10 < 9) #False
Pythonbool()
The bool() function allows you to evaluate any value, and give you True or False in return,
print(bool("Hello")) #True
print(bool(15)) #True
PythonMost Values are True
- Almost any value is evaluated as True if it has some sort of content.
- Any string is True, except empty strings.
- Any number is True, except 0.
- Any list, tuple, set, and dictionary are True, except empty ones.
Some Values are False
Values that are evaluated as False,
- empty values, such as (), [], {}, “”,
- the number 0
- The None
- And of course, the value False evaluates to False.
Give shorthand if …else example
a = 2
b = 330
print("A") if a > b else print("B") #B
PythonThis technique is known as Ternary Operators or Conditional Expressions.
Give examples of Positional and Keyword Arguments
Positional Argument: The value is passed to the function based solely on its position in the argument list.
def add(a, b):
return a + b
result = add("John ", "Doe") # 'John' goes to 'a', and 'Doe' goes to 'b' (based on position)
print(result) # Output: John Doe
PythonKeyword Argument: The value is passed using the parameter name explicitly.
result = add(b="Doe", a="John ") # Passing by parameter name
print(result) # Output: John Doe
PythonWhat are Positional-Only Arguments?
Positional-only arguments in Python are function parameters that can only be passed by position, not by keyword. This ensures that certain arguments are specified in a specific order without using their parameter names.
In Python, you define positional-only arguments by placing a / in the function definition. Any arguments defined before the / are positional only.
def function_name(arg1, arg2, /, arg3, arg4):
# Function body
PythonArguments before / are positional-only:
- These arguments cannot be passed using their names.
- They must be passed in the correct order.
Arguments after / can be passed by position or keyword:
- You can pass these arguments using their names or by their order.
The / itself is not a parameter but a separator indicating which arguments are positional-only.
def calculate(a, b, /, c, d):
print(a,b,c,d)
calculate(1,2,3,4) # 1 2 3 4 #Positional for all parameters
calculate(1,2,d=4,c=3) # 1 2 3 4
# Invalid calls:
#calculate(a=1, b=2, c=3, d=4) # TypeError: 'a' and 'b' are positional-only
#calculate(1, b=2, c=3, d=4) # TypeError: 'b' is positional-only
PythonWhat are Keyword-only arguments?
Keyword-only arguments are function parameters that can only be passed by their names, not by their position. This ensures clarity and prevents mistakes when calling the function, especially for optional or default parameters.
In Python, you define keyword-only arguments by placing a * in the function definition. Any parameters defined after the * must be passed as keywords.
def function_name(arg1, arg2, *, arg3, arg4):
pass
Pythonarg1 and arg2:
- These are positional or keyword arguments.
- They can be passed either by position or by name.
arg3 and arg4
- These are keyword-only arguments because they come after the *.
- They must be passed by their names explicitly.
# valid
function_name(1, 2, arg3=3, arg4=4) # All arguments provided correctly
function_name(arg1=1, arg2=2, arg3=3, arg4=4) # Passing everything by keyword
# Invalid
function_name(1, 2, 3, 4)
# TypeError: function_name() takes 2 positional arguments but 4 were given
function_name(1, 2, arg3=3)
# TypeError: missing a required argument: 'arg4'
function_name(arg1=1, arg2=2, 3, 4)
# SyntaxError: positional argument follows keyword argument
PythonCombine Positional-Only and Keyword-Only
You can combine the two argument types in the same function. Any argument before the /, is positional-only, and any argument after the *, is keyword-only.
def my_function(a, b, /, *, c, d):
print(a + b + c + d)
my_function(5, 6, c = 7, d = 8) #26
PythonWhat is the difference between is and == in Python?
- is: Checks for object identity. It verifies whether two references point to the same object in memory
- ==: Checks for equality. It determines whether the values of two objects are the same, regardless of whether they are the same object in memory.
a = [1, 2, 3]
b = a
print(b is a) True
print(b == a) True
# Make a new copy of list `a` via the slice operator,
# and assign it to variable `b`
b = a[:]
print(b is a) #False
print(b == a) #True
# Case 1
a = 1000
b = 1000
print(id(a)) #23066280615280
print(id(b)) #23066280615280
print(a is b) #True
print(1000 is 10**3) #True ,#Case 1
print(1000 == 10**3) #True
print("a" is "a") #True
print("aa" is "a" * 2) #True ,#Case 1
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2) # True: values are the same
print(list1 is list2) # False: different objects in memory
PythonCase 1: It works because Python caches small integer objects, which is an implementation detail. For larger integers, this does not work. Read about Python’s interning mechanism
Note: This question is often asked in python interviews
What is intern mechanism?
In the String Intern mechanism in Python, when we create two strings with the same value – instead of allocating memory for both of them, only one string is committed to memory. The other one just points to that same memory location.
However, The string interning behaviour in Python can differ based on several factors, including the version of Python, the implementation of the interpreter, and the context in which the string is created. As a result, identical string values may not always be interned, and the behaviour can be difficult to predict in certain cases.
One reason why the string interning result can differ for the same string in Python is that Python interns only string literals and not string objects that are created at runtime. This means if a string is executed at compile time are same then the reference is the same. But if the execution is done at run time then the reference(id) is different. Refer
Forcing Distinct Objects – bypass interning
a = int(1000) + 0 # Ensures a new integer object is created
b = int(1000) + 0 # Ensures another new integer object is created
print(a == b) # True: values are equal
print(a is b) # False: guaranteed to be distinct objects
PythonNote
- If you’re unsure whether Python will cache objects (like small integers or strings), you should avoid using is for value comparisons and instead use == to check for equality. This is the most reliable and portable approach.
- Use ‘is’ only when you explicitly want to check object identity, i.e., whether two variables point to the same object in memory
- Always use == to compare values unless you explicitly need to check for object identity.
- When in doubt, avoid writing code that depends on Python’s interning or caching optimizations; such code may behave differently across environments or versions.
What is the purpose of Python’s __init__.py file in packages?
The __init__.py
file plays an important role in Python packages. Here’s its purpose:
Indicates a Directory as a Package
- In earlier versions of Python (before 3.3), the presence of an __init__.py file was required to indicate that a directory is a Python package. Without this file, Python would not treat the directory as a package, and you couldn’t import modules from it.
- In modern Python versions (3.3 and later), __init__.py is optional, but its use is still common for package initialization or organizational purposes.
Package Initialization
- When a package is imported (e.g., import mypackage), the code in the __init__.py file is executed. This makes it useful for initializing the package by:
- Setting up package-level variables.
- Importing specific modules or submodules.
- Executing any setup code required when the package is imported.
Namespace Control
It allows control over what is exposed at the package level. You can define the __all__ list in __init__.py to specify which modules or objects are accessible when using from mypackage import *.
__all__ = ["module1", "module2"]
PythonConvenience Imports
- You can use __init__.py to aggregate imports so that users can access submodules or functions directly from the package without needing to know its internal structure. For example:
# mypackage/__init__.py
from .module1 import func1
from .module2 import func2
PythonWith this, users can do:
from mypackage import func1, func2
PythonCustom Behavior
- It can contain any Python code that you want to execute upon importing the package, such as logging or dynamically modifying the package.
Why Empty __init__.py file
An empty __init__.py simply serves as a marker that tells Python to treat the directory as a package. In modern Python (version 3.3 and later), even this is optional, as Python can infer a directory is a package without the file. However, it’s still a common practice to include an empty init.py file for clarity and backward compatibility.
What is __init()__?
The __init()__ method is a special class method known as the initializer or constructor. It is automatically called when a class object is created. The purpose of this method is to initialize the class’s attributes or perform any required setup for the object.
class ClassName:
def __init__(self, parameters):
# Initialization code
PythonWhat is __del__()
__del__()__ is a special method used to perform cleanup actions when an object is about to be destroyed. This is called a destructor.
class ClassName:
def __del__(self):
# Cleanup code here
PythonWhat is dunder?
The double underscores (__) in Python, often referred to as “dunder” (short for “double underscore”), are used to indicate special methods or magic methods. These methods have specific roles and behaviours defined by Python, and they are not meant to be called directly by the user. Instead, they are invoked automatically in certain situations.
Why Double Underscores?
- Namespace Avoidance: Double underscores help differentiate special methods from user-defined methods, reducing the risk of accidental name collisions.
- For example, your custom method init won’t conflict with Python’s __init()__.
- Readability: Using __ visually sets these methods apart, making code easier to understand.
List Special Methods
Here’s a list of some commonly used double underscore methods:
- __init__: Constructor for initializing new objects.
- __del__: Destructor for cleanup when an object is deleted.
- __str__: String representation of an object (used by str() or print).
- __repr__: Official string representation for debugging (used by repr()).
- __len__: Returns the length of an object (used by len()).
- __add__: Defines the behaviour of the + operator.
- __getitem__: Enables indexing or slicing (obj[index]).
- __setitem__: Handles item assignment (obj[index] = value).
Role of __init()__ in inheritance
Case 1: When parent has init() method, but child does’nt have
class Parent:
def __init__(self):
print("Parent initialized")
class Child(Parent):
pass
obj = Child() # Parent initialized
PythonCase 2: When both parent and child have the init() method.
If a child class defines its __init__()
method, it overrides the parent’s __init__()
class Parent:
def __init__(self):
print("Parent initialized")
class Child(Parent):
def __init__(self):
print("Child initialized")
obj = Child() # Child initialized
PythonCase 3: When both parent and child have the init() method, but we can use the parent’s init() method
you need to explicitly call its __init__()
method within the child class’s __init__()
method using super
class Parent:
def __init__(self):
print("Parent initialized")
class Child(Parent):
def __init__(self):
super().__init__()
print("Child initialized")
obj = Child()
#Parent initialized
#Child initialized
PythonGuess the output
class A:
def __init__(self):
print("A initialized")
class B(A):
def __init__(self):
super().__init__()
print("B initialized")
class C(A):
def __init__(self):
super().__init__()
print("C initialized")
class D(B, C):
def __init__(self):
super().__init__()
print("D initialized")
print(D.mro())
obj = D()
Python[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
A initialized
C initialized
B initialized
D initialized
Pythonread about MRO
Self Parameter
The self parameter in Python is a reference to the instance of the class itself. It is used within a class to access the instance’s attributes and methods.
self.attribute_name
self.method_name()
PythonKey Points About Self
- The first parameter of any instance method in a class must be self.
- It acts as a handle for the calling object, allowing access to its properties and other methods.
- Self is not a reserved keyword in Python; it’s just a naming convention. You could name it anything else, but using self is strongly recommended for readability and consistency.
Working
obj.method()
Pythonis internally converted to:
Class.method(obj)
PythonExample 1
class Person:
def __init__(self, name, age):
self.name = name # Instance variable
self.age = age # Instance variable
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
# Creating an instance of Person
person1 = Person("Alice", 30)
# Calling an instance method
print(person1.greet()) # Output: Hello, my name is Alice and I am 30 years old.
PythonExample 2: Use backendmesh as reference instead of self
class Animal:
def __init(backendmesh,name)__:
backendmesh.name = name
def speak(backendmesh):
print(backendmesh.name)
cat = Animal("cat")
cat.speak() # cat
PythonSuper function
In Python, super() is a built-in function used to call methods from a parent (or superclass) class. It is typically used in object-oriented programming (OOP) to invoke methods that are inherited from a parent class, especially when overriding them in a subclass.
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
super().speak() # Calls speak method of Animal class
print("Dog barks")
dog = Dog()
dog.speak()
#output
Animal speaks
Dog barks
PythonWhat is a pass statement in Python?
The pass statement is a placeholder that does nothing. It is used when a statement is syntactically required, but no action is necessary or the code is intentionally left blank.
Common Uses of Pass
Placeholder for Future Code: It can be used when writing a function, class, or loop where the implementation will be added later.
def my_function():
pass # Implementation will be added later
PythonEmpty Class: To define a class without any methods or properties for now.
class MyClass:
pass
PythonEmpty Loops: To include a loop that does nothing (often temporarily during debugging).
for i in range(10):
pass
PythonConditionals Without Actions: When you want to skip specific conditions.
x = 5
if x > 10:
pass # Do nothing if x is greater than 10
else:
print("x is less than or equal to 10")
PythonPass in an Abstract Class
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass # No implementation here; subclasses must define this method
class Dog(Animal):
def make_sound(self):
print("Woof!")
class Cat(Animal):
def make_sound(self):
print("Meow!")
# Using the classes
dog = Dog()
dog.make_sound() # Outputs: Woof!
cat = Cat()
cat.make_sound() # Outputs: Meow!
PythonIterator vs Iterable
Feature | Iterable | Iterator |
---|---|---|
Definition | Can be iterated over. | Used to fetch items from an iterable. |
Methods | Implements __iter__() . | Implements __iter__() and __next__() . |
Examples | Lists, tuples, sets, dictionaries. | The object returned by iter() function. |
State | Stateless. | Stateful (remembers its position). |
What is dir() frunction
The dir() function in Python is used to return a list of the attributes and methods available in a given object. If called without arguments, it returns the list of names in the current local scope.
Without Arguments:
print(dir())
#['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
PythonThis will list the names currently defined in the local scope.
With an Object:
print(dir(str))
#['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
PythonThis will list all the attributes and methods of the str class.
Custom class
# Define a custom class
class MyClass:
class_var = "Hello, World!"
def __init__(self, value):
self.instance_var = value
def say_hello(self):
return "Hello from MyClass!"
def display_value(self):
return f"The value is: {self.instance_var}"
# Create an instance of the class
my_object = MyClass(42)
# Use dir() to inspect the class
print("Attributes and methods in MyClass:")
print(dir(MyClass))
# Use dir() to inspect the object instance
print("\nAttributes and methods in my_object:")
print(dir(my_object))
#output
Attributes and methods in MyClass:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'class_var', 'display_value', 'say_hello']
Attributes and methods in my_object:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'class_var', 'display_value', 'instance_var', 'say_hello']
PythonOutput:
This will display all the attributes and methods available for MyClass and the my_object instance. It will include:
- Your defined methods (say_hello, display_value)
- Built-in methods and attributes such as __init__, __class__, and __repr__
- Variables such as class_var and instance_var (accessible depending on the context).
What is PIP?
PIP is a package manager for Python packages.
- Pip uses the Python Package Index (PyPI) as the default repository for fetching packages, but it can also install packages from other sources.
- Pip stands for “pip Install Packages”
Purpose of else in Try-Except
- The try block lets you test a block of code for errors.
- The except block lets you handle the error.
- The else block lets you execute code when there is no error.
- The finally block lets you execute code, regardless of the result of the try- and except blocks.
Key Differences Between else and finally
- else: Runs only if the try block completes successfully without exceptions.
- finally: Always runs, whether an exception occurs or not, and even if the try or except block contains a return, break, or continue.
Tricky question: Guess the Output
def test_function():
try:
return "Try block return"
finally:
print("Finally block executed.")
result = test_function()
print(result)
PythonOutput
Finally block executed.
Try block return
PythonThe finally block will execute before the return value is sent back to the caller.
Why should broad exception handling (using except Exception
) be avoided?
Broad exception handling should be avoided because it can mask bugs, suppress critical errors, and make debugging difficult. When you catch all exceptions, you risk hiding issues like SyntaxError or NameError, which are important to address. It also prevents proper handling of specific problems, such as network errors or file access issues, and can lead to unintended side effects, like incorrect results or data corruption. Instead, it’s better to catch specific exceptions (e.g., ValueError, KeyError) that are expected in the context of the code, and for unexpected exceptions, log them and re-raise them for proper tracking. This approach ensures that your code is more maintainable, predictable, and easier to debug while still gracefully handling issues when they arise.
Example of Broad Exception Handling (to avoid):
try:
# Some code that could raise different types of exceptions
result = 10 / 0 # Division by zero will raise ZeroDivisionError
data = {"key": "value"}
print(data["non_existent_key"]) # This will raise KeyError
except Exception as e: # Catching all exceptions
print(f"An error occurred: {e}")
PythonProblems with this approach:
- Masking specific errors: It catches all exceptions, including ZeroDivisionError and KeyError, but it doesn’t tell us where or why those specific errors occurred.
- Debugging difficulty: You lose important context about what went wrong, making debugging much harder.
- Silencing critical issues: Unexpected errors could be hidden, preventing you from identifying the root cause.
Better Approach: Catching Specific Exceptions
try:
# Some code that could raise different types of exceptions
result = 10 / 0 # Division by zero will raise ZeroDivisionError
except ZeroDivisionError as e:
print(f"Cannot divide by zero: {e}")
try:
data = {"key": "value"}
print(data["non_existent_key"]) # This will raise KeyError
except KeyError as e:
print(f"Missing key in dictionary: {e}")
PythonBenefits of this approach:
- Specific error handling: Each exception (ZeroDivisionError and KeyError) is caught separately, allowing you to handle them appropriately.
- Clear debugging: The error messages provide more context about where the problem occurred and why.
- No masking: Errors are explicitly addressed without suppressing them, making it easier to identify and fix issues.
By catching specific exceptions, you ensure that the program reacts to errors in a predictable and controlled way, which makes your code easier to maintain and debug.
How would you ensure a Python script is compatible across Python 2 and Python 3?
Ensuring compatibility between Python 2 and Python 3 involves careful design and use of libraries that work across both versions. Here’s a comprehensive guide:
Compatibility Layer
A compatibility layer in the context of Python is a library or framework that helps developers write code that works seamlessly across both Python 2 and Python 3 without requiring separate code bases. These layers provide abstractions and helper functions to deal with differences in syntax, built-in functions, modules, and behaviour between the two Python versions.
Common Compatibility Layers
future
Library
The future package allows you to write code in a Python 3 style that also works in Python 2.
from __future__ import print_function, division, absolute_import, unicode_literals
Pythonsix Library
The six library is lightweight and provides utilities for writing code compatible with Python 2 and Python 3.
from six.moves import queue
q = queue.Queue()
PythonMigration Approach
If possible, migrate code to Python 3 using tools like 2to3 or futurize. This way, you maintain Python 3 compatibility while supporting Python 2.
What is the purpose of ABC?
ABC stands for Abstract Base Class in Python. It provides a way to define abstract classes, which serve as a blueprint for other classes. Using the abc module, ABCs ensure that derived classes implement specific methods, making it a useful tool for enforcing a consistent interface.
Purpose of ABC:
- Enforce Method Implementation: Abstract base classes allow you to define methods that must be implemented in any subclass. If a subclass fails to implement the abstract methods, Python raises a TypeError.
- Encourage Code Reusability: By defining common interfaces and behaviour in an abstract class, derived classes can reuse those implementations, reducing redundancy.
- Provide a Template: ABCs are used to outline the methods and properties a class should have, serving as a guideline for developers.
- Enable Polymorphism: ABCs ensure that different objects adhering to the same interface can be treated interchangeably in the code.
- Support for Type Checking: Using ABCs, you can check if an object is an instance of a certain abstract class or implements a specific interface.
from abc import ABC, abstractmethod
# Define an Abstract Base Class
class Animal(ABC):
@abstractmethod
def sound(self):
pass
@abstractmethod
def habitat(self):
pass
# Subclass implementing the abstract methods
class Dog(Animal):
def sound(self):
return "Bark"
def habitat(self):
return "Domestic"
class Fish(Animal):
def sound(self):
return "Blub"
def habitat(self):
return "Water"
# Instantiate and use the subclasses
dog = Dog()
fish = Fish()
print(dog.sound()) # Output: Bark
print(fish.habitat()) # Output: Water
Python- The Animal class is an abstract base class.
- Dog and Fish are concrete implementations of Animal, ensuring they define sound and habitat.
What is a metaclass in Python?
A metaclass in Python is a “class of a class” that defines how a class behaves. Just like a class defines the behaviour and properties of objects, a metaclass defines the behaviour and properties of classes. Essentially, metaclasses allow you to control the creation, modification, and behaviour of classes themselves.
By default, Python uses the built-in metaclass type to create classes, but you can define your metaclass by inheriting from type.
When to Use Metaclasses
Metaclasses are typically used when you need to:
- Enforce coding standards or ensure specific patterns in class definitions.
- Automatically modify or add methods/attributes to classes when they’re defined.
- Implement frameworks or libraries where certain rules or behaviours need to be standardized across many classes.
How can you debug a Python script?
Debugging a Python script effectively involves various tools and techniques. Here are three common methods:
- Using Built-in Debugging Tools: pdb (Python Debugger)
- Print Statements
- IDE Debugging Features
- Integrated Development Environments (IDEs) like PyCharm, VS Code, or Jupyter Notebooks have built-in debugging tools with graphical interfaces.
- Features like breakpoints, variable inspection, and step-by-step execution make it easier to locate and resolve issues
You are given a large dataset that doesn’t fit into memory. How would you process it?
Use Chunking with Libraries:
Many libraries support processing large datasets in chunks.
Pandas
import pandas as pd
# Read the dataset in chunks
chunk_size = 100000 # Number of rows per chunk
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# Process each chunk
print(chunk.head()) # Example: Print the first few rows of each chunk
PythonDask: Dask provides a scalable way to process large datasets.
import dask.dataframe as dd
# Load a large CSV file as a Dask DataFrame
df = dd.read_csv('large_file.csv')
# Perform operations (these are lazy and will compute only when needed)
result = df.groupby('column_name').mean()
# Compute the result
result.compute()
PythonUse Generators for Lazy Loading
Generators allow you to load and process data lazily, row by row or in small chunks.
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line # Yield one line at a time
# Process the file
for line in read_large_file('large_file.txt'):
print(line) # Example: Print each line
PythonUse Database Queries
Instead of loading the entire dataset into memory, query only the required data from a database.
Utilize File Formats Designed for Large Data
File formats like Parquet or HDF5 are optimized for large datasets and allow partial reads.
Parallel or Distributed Processing
Divide the dataset and process parts in parallel using tools like multiprocessing, Ray, or Dask.
Stream Data with Libraries
For specific formats like JSON, use libraries that support streaming.
Conclusion
Learning the basics of Python is the first step toward unlocking its vast potential. From understanding variables and control flow to working with data structures and functions, these fundamental concepts are essential for solving real-world problems with Python. With practice, you can confidently advance to more complex topics like object-oriented programming, file handling, and working with external libraries. Embrace the learning process, experiment with code, and enjoy the simplicity and power that Python offers.
3 thoughts on “Essential 50+ Python Interview Questions”