Data Science Python Interview Questions
Question: How do you handle exceptions in Python?
Answer:
In Python, exceptions are handled using the try
, except
, else
, and finally
blocks. These blocks allow you to catch errors and handle them gracefully without crashing your program. Here’s a detailed breakdown of how you can handle exceptions:
1. try
Block:
- The
try
block is used to wrap the code that may raise an exception. - If an exception occurs within the
try
block, Python will stop executing the rest of the code in the block and move to theexcept
block.
Example:
try:
# Code that may raise an exception
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
In this example, dividing by zero raises a ZeroDivisionError
, which is caught by the except
block.
2. except
Block:
- The
except
block is used to catch and handle specific exceptions. - You can specify the type of exception you want to catch (e.g.,
ZeroDivisionError
,ValueError
, etc.). - If no exceptions occur in the
try
block, theexcept
block is skipped.
Example (Catching a specific exception):
try:
num = int(input("Enter a number: "))
except ValueError:
print("Invalid input, please enter a valid integer.")
In this example, if the user enters a non-integer, a ValueError
will be raised, and the message “Invalid input…” will be printed.
3. else
Block:
- The
else
block, if present, will be executed if no exceptions are raised in thetry
block. - It is typically used to run code that should only be executed when the
try
block is successful.
Example:
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero!")
else:
print(f"Result is {result}")
In this case, since no exception occurs, the else
block will execute, printing “Result is 5.0”.
4. finally
Block:
- The
finally
block, if present, will always execute after thetry
andexcept
blocks, regardless of whether an exception was raised or not. - It is typically used for cleanup operations, like closing files, releasing resources, or ensuring that certain code is always run.
Example:
try:
file = open('example.txt', 'r')
content = file.read()
except FileNotFoundError:
print("File not found!")
finally:
file.close() # This will always execute, even if an exception is raised.
print("File is closed.")
In this example, the finally
block ensures that the file is closed even if an error occurs while reading the file.
5. Catching Multiple Exceptions:
You can catch multiple exceptions in a single except
block or use multiple except
blocks for different exceptions.
Example (Multiple exceptions):
try:
x = int(input("Enter a number: "))
y = 10 / x
except ValueError:
print("That's not a valid number!")
except ZeroDivisionError:
print("You can't divide by zero!")
In this example:
- If the user enters a non-integer, the
ValueError
block will handle it. - If the user enters
0
, theZeroDivisionError
block will handle it.
6. Catching All Exceptions (Not Recommended):
You can catch all exceptions using a generic except
clause, but it is generally not recommended because it may catch unexpected exceptions, making debugging difficult.
Example (Catching all exceptions):
try:
x = int(input("Enter a number: "))
y = 10 / x
except Exception as e:
print(f"An error occurred: {e}")
This will catch any exception, and the error message will be displayed.
Note: It’s better to catch specific exceptions to handle different types of errors appropriately.
7. Raising Exceptions:
You can also raise exceptions intentionally using the raise
keyword. This is useful when you want to trigger an error condition in your code.
Example:
def divide(a, b):
if b == 0:
raise ValueError("The denominator cannot be zero.")
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(e)
In this case, a ValueError
is raised if the denominator is zero, and the error message is printed.
Summary of Exception Handling Blocks:
try
: Wraps the code that might raise an exception.except
: Handles exceptions that occur in thetry
block.else
: Runs if no exception occurs in thetry
block.finally
: Always runs, whether an exception occurred or not.
Conclusion:
Exception handling in Python allows you to gracefully manage errors, ensuring that your program continues to run smoothly even when unexpected situations arise. By using the try
, except
, else
, and finally
blocks, you can handle different kinds of errors, clean up resources, and keep your program robust and user-friendly.
Question: What are Python’s namespaces?
Answer:
A namespace in Python refers to a container where names (identifiers) are mapped to objects. In simple terms, it is a space that holds all the variable names and their corresponding objects (values). These namespaces are used to keep track of variable names in a way that allows Python to know what each variable refers to.
Namespaces help in preventing naming conflicts by ensuring that each variable name is unique within its specific namespace. When you refer to a variable or function in Python, the interpreter uses the namespace to figure out what value that name points to.
Types of Namespaces in Python:
-
Built-in Namespace:
- This is the namespace that contains built-in objects like functions, exceptions, and other standard Python objects (e.g.,
print()
,len()
,int()
, etc.). - It is created when Python starts and exists as long as the interpreter is running.
- This is the namespace that contains built-in objects like functions, exceptions, and other standard Python objects (e.g.,
-
Global Namespace:
- This namespace refers to the top-level environment where functions and variables are defined. It exists for the duration of the program’s execution.
- The global namespace is created when the program is executed, and variables/functions defined at the top level are part of this namespace.
-
Local Namespace:
- This namespace exists inside a function or method. It contains the names of variables and functions local to that specific function or block of code.
- A new local namespace is created when a function is called, and it is destroyed when the function execution is complete.
-
Enclosing Namespace:
- This namespace refers to variables that are in the outer (enclosing) scope of a function. It is relevant when working with nested functions, where an inner function can access variables from an outer function’s scope.
- It lies between the global and local namespaces in terms of scope.
How Python Resolves Names: LEGB Rule
Python uses the LEGB rule (Local, Enclosing, Global, Built-in) to resolve the names of variables and functions. When Python encounters a name, it searches for that name in the following order:
- Local: The namespace of the current function or method.
- Enclosing: The namespace of any enclosing functions (if the current function is nested inside another).
- Global: The top-level namespace, where variables and functions are defined in the main program.
- Built-in: The built-in namespace, which contains Python’s built-in functions and objects.
Example of LEGB Rule:
x = "global x"
def outer():
x = "outer x"
def inner():
x = "inner x"
print(x) # This will print the value of 'x' in the local namespace of inner function
inner()
outer()
- In this case:
- The inner function
inner()
first looks forx
in its local scope (and finds"inner x"
). - If it didn’t find
x
there, it would check the enclosing scope, i.e., theouter()
function (and find"outer x"
). - If still not found, it would check the global scope (and find
"global x"
). - Finally, if not found in any of the above, it would look in the built-in namespace (but there is no built-in
x
).
- The inner function
The output of the code will be:
inner x
This is because Python first looks in the local namespace of the inner()
function, finds the variable x
, and prints it.
Modifying Variables in Different Namespaces:
-
Global Variables: You can modify a global variable inside a function using the
global
keyword.x = 10 # global variable def modify_global(): global x x = 20 # modifies the global 'x' modify_global() print(x) # Output: 20
-
Nonlocal Variables: You can modify a variable in the enclosing (non-global) namespace using the
nonlocal
keyword, typically in the case of nested functions.def outer(): x = 10 # variable in the enclosing namespace def inner(): nonlocal x x = 20 # modifies the enclosing 'x' inner() print(x) # Output: 20 outer()
How Python Uses Namespaces:
- Function Calls: When a function is called, a new local namespace is created, and any local variables inside that function are stored there.
- Global Scope: Variables declared outside any function or class are stored in the global namespace. The global namespace is accessible throughout the program unless shadowed by a local or enclosing namespace.
- Built-in Scope: Python comes with many built-in objects, such as exceptions, functions, and types, which are available across the program through the built-in namespace.
Namespaces and Memory Management:
Namespaces help Python manage memory more efficiently. When variables go out of scope, they are removed from their respective namespaces, making the memory available for reuse. For example, local variables in a function are deleted when the function ends.
Conclusion:
Namespaces in Python help organize the various identifiers (variables, functions, etc.) by ensuring that each one is uniquely associated with a specific scope. This organization allows Python to resolve names efficiently and avoid conflicts. Understanding namespaces and the LEGB rule is crucial for managing variable scope and properly accessing and modifying variables in different parts of a program.
Read More
If you can’t get enough from this article, Aihirely has plenty more related information, such as Python interview questions, Python interview experiences, and details about various Python job positions. Click here to check it out.
Tags
- Python
- Python interview questions
- Python decorators
- Global Interpreter Lock
- Memory management
- List vs tuple
- Shallow copy
- Deep copy
- Python generators
- Exception handling
- Lambda function
- Python namespaces
- File modes
- Static method
- Class method
- Serialization
- Python 2 vs Python 3
- Debugging
- Stack and queue in Python
- Serialization in Python
- Python data structures
- Python comprehensions
- Mutable vs immutable
- Python coding interview
- Python fundamentals
- Exception handling in Python