

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Decorators
incomplete
2: Args and Kwargs
incomplete
3: Args and Kwargs Practice
incomplete
4: Decorators
incomplete
5: Decorators Review
incomplete
6: LRU Cache
incomplete
7: Decorators Practice
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Remember function transformations, where a (higher-order) function takes a function and returns a function with new behavior? Python decorators offer a kind of syntactic sugar around that. ("Syntactic sugar" just means "a more convenient syntax.")
Example:
from collections.abc import Callable
def vowel_counter(func_to_decorate: Callable[[str], None]) -> Callable[[str], None]:
vowel_count: int = 0
def wrapper(doc: str) -> None:
nonlocal vowel_count
vowels: str = "aeiou"
for char in doc:
if char.lower() in vowels:
vowel_count += 1
print(f"Vowel count: {vowel_count}")
func_to_decorate(doc)
return wrapper
@vowel_counter
def process_doc(doc: str) -> None:
print(f"Document: {doc}")
process_doc("What")
# Vowel count: 1
# Document: What
process_doc("A wonderful")
# Vowel count: 5
# Document: A wonderful
process_doc("world")
# Vowel count: 6
# Document: world
The @vowel_counter line is "decorating" the process_doc function with the vowel_counter function. vowel_counter is called once when process_doc is defined with the @ syntax, but the wrapper function that it returns is called every time process_doc is called. That's why vowel_count is preserved and printed after each time.
Python decorators are just another (sometimes simpler) way of writing a higher-order function. These two pieces of code are identical:
@vowel_counter
def process_doc(doc: str) -> None:
print(f"Document: {doc}")
process_doc("Something wicked this way comes")
def process_doc(doc: str) -> None:
print(f"Document: {doc}")
process_doc = vowel_counter(process_doc)
process_doc("Something wicked this way comes")
The provided file_type_aggregator function is intended to decorate other functions. It assumes that the function it decorates has exactly 2 positional arguments.
Create a process_doc function that is decorated by file_type_aggregator. It should return the following string:
f"Processing doc: '{doc}'. File Type: {file_type}"
Where doc and file_type are its positional arguments. (See the line where result is assigned to func_to_decorate(doc, file_type).)