1. What are Python decorators and how do they work?
o Answer: Decorators are a way to modify or extend the
behavior of functions or methods without changing their
actual code. They are defined with
the @decorator_name syntax and wrap another function.
Example:
Python
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
2. Explain the Global Interpreter Lock (GIL) in Python.
o Answer: The GIL is a mutex that protects access to Python
objects, preventing multiple native threads from executing
Python bytecodes at once. This means that even in multi-
threaded programs, only one thread executes Python code at
a time. It simplifies memory management but can be a
bottleneck in CPU-bound multi-threaded programs.
3. What is the difference between deepcopy and copy in Python?
o Answer: The copy module provides two
functions: copy() and deepcopy(). copy() creates a shallow
copy of an object, meaning it copies the object’s structure but
not the nested objects. deepcopy() creates a deep copy,
meaning it recursively copies all nested objects.
Python
import copy
original = [1, [2, 3], 4]
shallow = copy.copy(original)
deep = copy.deepcopy(original)
4. How do you manage memory in Python?
o Answer: Python uses automatic memory management,
primarily through reference counting and garbage collection.
The gc module provides an interface to the garbage collector,
allowing manual control over the collection process. Memory
management techniques include using weak references and
context managers to ensure resources are properly released.
5. What are metaclasses in Python?
o Answer: Metaclasses are classes of classes that define how
classes behave. A class is an instance of a metaclass.
Metaclasses allow customization of class creation, enabling
advanced features like class decorators and dynamic class
creation. Example:
Python
class Meta(type):
def __new__(cls, name, bases, dct):
print(f"Creating class {name}")
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=Meta):
pass