1. Understanding Decorators¶
Decorators are not exclusive to Python Flask but are widely used across various programming languages.
Before using decorators from Flask, it is essential to understand the underlying concepts of decorators.
2. What are First-class Functions and Closures?¶
A nested function is a function defined inside another function and can be invoked outside its parent function.
def outer_func(num):
print('call outer_func function')
# The nested function can access variables from the enclosing function
def inner_func():
# Accessing 'num' from the outer function
print(num)
return 'complex'
# Returning the nested function as a result
return inner_func
# First-class function example: Assigning a function to a variable
# 'outer_func' returns 'inner_func'
fn = outer_func(10)
# Calling the returned 'inner_func'
inner_res = fn()
# Closure: The returned function retains access to 'num' from 'outer_func'
print(inner_res)
call outer_func function 10 complex
2.1. Nested Function¶
A function defined inside another function.
Nested functions can be called and returned within the function where they are defined.
The variables declared inside the function are accessible only within that function, following the same principle as local variables.
# Define an outer function that prints a message and calls a nested function
def outer_func():
print('call outer_func function')
# Define a nested function (inner function) inside the outer function
def inner_func():
return 'call inner_func function'
# Call the inner function and print its returned message
print(inner_func())
# Call the outer function
outer_func()
call outer_func function call inner_func function
# A nested function cannot be called from outside the function where it is defined
inner_func()
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[1], line 2 1 # A nested function cannot be called from outside the function where it is defined ----> 2 inner_func() NameError: name 'inner_func' is not defined
3. First-class Function¶
A function is considered a first-class function if it can be treated as follows:
- Can be stored in a variable.
- Can accept other functions as arguments.
- Can return a function as its output.
Python and First-class Functions
- In Python, functions are objects, allowing them to be used like objects in addition to their basic functionality as functions.
def calc_square(digit):
return digit * digit
calc_square(2)
# A function can be assigned to a variable named func1
func1 = calc_square
print(func1)
# Using the variable func1 as a function works the same as calling the calc_square function directly
func1(2)
<function calc_square at 0x7f54a8ee21f0>
4
# A function can accept another function as an argument
def calc_square(digit):
return digit * digit
def calc_plus(digit):
return digit + digit
def calc_quad(digit):
return digit * digit * digit * digit
def list_square(func, digit_list):
result = []
for digit in digit_list:
result.append(func(digit))
print(result)
num_list = [1,2,3,4,5]
list_square(calc_square, num_list)
list_square(calc_plus, num_list)
list_square(calc_quad, num_list)
[1, 4, 9, 16, 25] [2, 4, 6, 8, 10] [1, 16, 81, 256, 625]
# A function can return another function as its result
def logger(msg):
message = msg
def write_msg():
print(f'[ERROR]: {message}')
return write_msg
log1 = logger('invalid value')
print(log1)
log1()
<function logger.<locals>.write_msg at 0x7fddd46bd670> [ERROR]: invalid value
# Even if the logger function is deleted,
# the log1() function retains access to the write_msg function
# inside the logger function along with the value of msg.
del logger
log1()
[ERROR]: invalid value
3.1. Using First-class Functions¶
def html_creator(tag):
# Nested function to wrap a message with the specified HTML tag
def text_wrapper(msg):
print (f'<{tag}>{msg}</{tag}>')
return text_wrapper
h1_html_creator = html_creator('h1')
print(h1_html_creator)
h1_html_creator('the "h1" tag is used to display titles')
<function html_creator.<locals>.text_wrapper at 0x7f97726ca790> <h1>the "h1" tag is used to display titles</h1>
p_html_creator = html_creator('p')
p_html_creator('The "p" tag is used to display paragraphs.')
<p>The "p" tag is used to display paragraphs.</p>
def index_creator(char):
def text_wrapper(msg_list):
for msg in msg_list:
print(f'{char} {msg}')
return text_wrapper
func1 = index_creator('*')
func1(['Hello', 'my name is', 'WoongKeol Kim'])
* Hello * my name is * WoongKeol Kim
4. Closure Function¶
A technique where a function and the data it holds are copied and stored together for use as a separate function (similar to First-class functions).
Even after the outer function is destroyed, the local variables inside the outer function and the nested function (inner function) can still be accessed.
def outer_func(num):
# Key concept of a closure: The nested function can access the outer function's variable
# inner_func can access the outer variable 'num' even after outer_func has finished executing
def inner_func():
print(num)
return 'Hello, this is inner function!'
return inner_func
# First-class function
closure_func = outer_func(10)
# Call the closure
print(closure_func())
10 Hello, this is inner function!
# Even if the outer_func function is deleted,
# the inner_func() function and the value of num are still retained.
del outer_func
print(closure_func())
10 Hello, this is inner function!