once¶
Function Name: once¶
Overview and Introduction¶
In a variety of contexts, whether while initializing some variables, setting up logging, or ensuring some heavy computation isn't undertaken multiple times, there are scenarios where you might want to ensure a function is executed only once. The once
function is a Python decorator that took up this challenge. By using it, we guarantee a wrapped function is called only for the first time it is invoked.
The once
function meets this requirement by retaining a flag called
in its closure. This flag tracks whether or not a function has been called before. When the function is called, it checks the flag. If the flag is false (False
), implying the function hasn't been called before, it allows the function to execute and toggles the flag. If the flag is true (True
), indicating the function has been called before, it simply returns, preventing the function execution.
Function Definition¶
Let's consider the structure and details of the once
function. It accepts a single argument, fn
, which is the function to be wrapped. The function is returned as the output after being wrapped in a closure that maintains the called
flag.
def once(fn):
"""
Decorator to ensure the function is only called once.
Args:
fn (function): The function to wrap.
Returns:
function: The wrapped function.
"""
called = False
@wraps(fn)
def inner(x):
nonlocal called
if called:
return
called = True
return fn(x)
return inner
Argument | Type | Description |
---|---|---|
fn | function | The function to wrap. |
Functionality and Usage¶
The once
function ensures that the annotated function fn
is executed only once - the first time it's called. For all subsequent calls, it immediately returns without executing the function fn
. The once
decorator therefore is particularly useful in scenarios where a specific function should not or need not be executed more than once.
Example - Initial Setup Function¶
Let's demonstrate the once
function with a setup function, setup()
. This could represent any kind of initialization logic that should only be run once:
@once
def setup():
print("Setting up...")
# The setup() function is invoked twice.
setup() # Prints: 'Setting up...'
setup() # Doesn't print anything.
Example - Heavy Computation Function¶
Here is an example where a computation should only be executed once:
@once
def heavy_computation():
print("Doing heavy computation...")
# long running computation
# The heavy_computation() function is invoked twice.
heavy_computation() # Prints: 'Doing heavy computation...'
heavy_computation() # Doesn't print anything.
Example - State Initialisation¶
If you are dealing with a stateful class and need to initialize something only once, once
decorator can come handy:
class MyClass:
@once
def initialize(self):
print("Initializing state...")
# MyClass object is created, the initialize function is called twice.
obj = MyClass()
obj.initialize() # Prints: 'Initializing state...'
obj.initialize() # Doesn't print anything.
In each of the above examples, similarly, the decorated function setup()
, heavy_computation()
and initialize()
were called multiple times but executed only once.
The use of once
decorator provides a convenient way to ensure specific functions only run their core execution once, while allowing them to be flexibly called without caution multiple times elsewhere in code or scripts. This helps maintain cleaner and more predictable code especially when dealing with initializations and one-time setups.