What are Decorators?
Question Explanation
Decorators are a powerful feature in programming languages like Python that allow you to modify or enhance the behavior of functions or methods. They are essentially functions that wrap another function, adding functionality before or after the original function runs. Interviewers often ask about decorators to assess a candidate's understanding of higher-order functions, closures, and code reusability. This knowledge is crucial in modern software development where clean, maintainable code is a priority. Understanding decorators can also demonstrate familiarity with design patterns and functional programming principles. Many developers use decorators for tasks such as logging, access control, and memoization. Common pitfalls include misunderstanding how decorators affect function signatures and scope. Thus, being able to explain decorators comprehensively reflects a candidate's depth of knowledge and ability to write efficient, Pythonic code. Additionally, decorators connect to various areas such as middleware in web frameworks and aspect-oriented programming, showcasing their versatility in real-world applications.
Sample Answers
Example 1: Basic Decorator Implementation
A decorator is a function that takes another function as an argument and extends its behavior without explicitly modifying it. Here's a simple example:
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()
In this code, my_decorator wraps the say_hello function. When you call say_hello, it first executes the code in wrapper, demonstrating how decorators can enhance functionality. This pattern is particularly useful for logging, authentication, and other cross-cutting concerns.
Example 2: Decorators with Arguments
Decorators can also accept arguments, which adds flexibility to their use. Here's an example of a decorator that takes a parameter:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator_repeat
@repeat(3)
def greet(name):
print(f'Hello, {name}!')
greet('Alice')
In this case, repeat is a decorator factory that creates a decorator that repeats the greeting function a specified number of times. This showcases how decorators can be tailored for different needs, increasing code reusability and maintainability.
Example 3: Chaining Multiple Decorators
You can also apply multiple decorators to a single function, which allows for more complex behaviors. Here's an example:
def bold(func):
def wrapper(*args, **kwargs):
return f'\033[1m{func(*args, **kwargs)}\033[0m'
return wrapper
def italic(func):
def wrapper(*args, **kwargs):
return f'\033[3m{func(*args, **kwargs)}\033[0m'
return wrapper
@bold
@italic
def say_hi():
return 'Hi!'
print(say_hi())
In this example, both bold and italic decorators are applied to say_hi, showcasing how decorators can be stacked to create layered functionality. This technique is particularly useful in web frameworks and GUI applications where you want to apply multiple modifications to a single function.
Keywords
Ready to practice more questions?
Explore our collection of technical interview questions from top companies.
View All Questions