Loop Best Practices
What is a Loop?
A loop in DataCards allows notebooks to execute repeatedly until a specific termination condition is met. Loops are useful for iterative processing, parameter optimization, version control and simulation runs.
Isolation Principle
Critical Rule: Two loops must not touch each other - an element (variable or cell) should not be shareable between different loops.
Each loop must have its own variables to prevent state corruption and ensure reproducible behavior.
# âś… GOOD: Each loop has its own variables
datacards.publish.variable(key="loop1_counter", value=0)
datacards.publish.variable(key="loop2_counter", value=0)
# ❌ BAD: Shared variables between loops
datacards.publish.variable(key="shared_counter", value=0) # Used by both loops
Loop Scope
Loops can be implemented in one notebook or across multiple notebooks, depending on the use case.
- Single notebook: Simple iterative tasks
- Multiple notebooks: Complex workflows requiring different processing stages
State Management
Important: Never reset state within a loop. Use separate notebooks for state initialization.
How to Reset a Loop
Create a separate notebook to reset loop state:
# Reset Notebook - Run this to restart the loop
datacards.publish.variable(key="loop_counter", value=0)
datacards.publish.variable(key="loop_active", value=True)
Never reset variables from within the loop itself - this causes unpredictable behavior and potential infinite loops.
When to Use Loops
Only use loops if you need to use the state from previous iterations. If you don’t need historical state, consider using parallel execution instead.
Termination Criteria
Every loop must have a clear termination criterion to prevent infinite execution.
# Counter-based termination
max_iterations = 100
current_iteration = datacards.consume.variable.iteration_count()
if current_iteration >= max_iterations:
datacards.publish.variable(key="loop_active", value=False)
Loop Architecture
Recommendation: Implement loops as separate notebooks from the main workflow for better debugging.
Separate notebooks make it easier to:
- Debug loop behavior independently
- Test loop logic without affecting main workflow
- Manage loop state clearly
- Handle errors without crashing the main workflow
Example: Counter Loop
Let’s create a simple counter that automatically increments until it reaches a target value. This demonstrates how two cards can work together to create a loop.
The Setup
Create two cards:
- Integer Slider Card - for user input and loop control
- Number Card - to display the current counter value
The Code
Integer Slider Card:
# Read the incremented value from the number card
current_value = datacards.consume.variable.counter_value()
# If we haven't reached our target, update the slider
if current_value <= 42:
datacards.publish.variable("slider_value", current_value)
Number Card:
# Read the slider value
slider_value = datacards.consume.variable.slider_value()
# Display the current value
datacards.publish.card(
type='number',
value=slider_value,
label='Counter',
description='Auto-incrementing counter'
)
# Increment and publish for the next iteration
datacards.publish.variable("counter_value", slider_value + 1)
How It Works
When you set the slider to a low value (like 5), the loop begins:
- Number card reads the slider value (5) and displays it
- Number card increments it (6) and publishes the new value
- Slider card reads the incremented value (6) and updates itself
- This continues until the counter reaches 42, then stops
The loop automatically runs until it hits the termination condition, demonstrating how cards can work together to create iterative behavior.