Showing posts with label Python tutorial. Show all posts
Showing posts with label Python tutorial. Show all posts

Wednesday, January 8, 2025

Animating a Growing Circle with Python and Matplotlib


Circle Radius Animation in Python – Step-by-Step Guide

๐ŸŽฅ Growing Circle Animation – Learn Step by Step

Imagine a small dot at the center of your screen… slowly expanding into a larger circle. This simple animation teaches an important concept: how to visually represent change over time using math and programming.


๐Ÿ“š Table of Contents


๐Ÿ’ก Concept Overview

The goal is simple:

  • Start with a tiny circle
  • Gradually increase its radius
  • Keep it centered at (0, 0)
  • Create a smooth animation
This is a perfect example of combining math + visualization.

๐Ÿ“ Mathematics Behind the Animation

1. Circle Equation

\[ x^2 + y^2 = r^2 \]

This defines a circle centered at the origin.

2. Radius Growth Function

\[ r = i \times 0.5 \]

Where:

  • r = radius
  • i = frame number
๐Ÿ‘‰ Each frame increases the radius linearly.

3. Time-Based Animation

\[ Time = frames \times interval \]

Example:

\[ 30 \times 50ms = 1500ms (1.5 seconds) \]


⚙️ Step-by-Step Breakdown

Click to expand steps
  • Create 2D plot with limits (-10 to 10)
  • Initialize small circle
  • Update radius each frame
  • Redraw circle smoothly
  • Maintain equal aspect ratio

๐Ÿ’ป Python Code

import matplotlib.pyplot as plt import matplotlib.animation as animation fig, ax = plt.subplots() ax.set_xlim(-10, 10) ax.set_ylim(-10, 10) ax.set_aspect('equal') circle = plt.Circle((0, 0), 0.05) ax.add_patch(circle) def update(frame): radius = frame * 0.5 circle.set_radius(radius) return circle, ani = animation.FuncAnimation(fig, update, frames=30, interval=50) plt.title("Simple Circle Animation") plt.show()

๐Ÿ–ฅ️ Output Description

What you will see
- A small circle appears at the center
- It expands smoothly outward
- Growth is continuous and fluid
- Ends as a large circle within bounds

๐Ÿ’ก Key Takeaways

  • Animations are just repeated updates over time
  • Math controls motion and growth
  • Linear functions create smooth scaling
  • Visualization improves understanding

๐ŸŽฏ Final Thought

What starts as a simple expanding circle is actually a powerful lesson in how math and code work together to create motion.

Once you understand this, you can animate anything.

Monday, September 23, 2024

Python nonlocal Keyword Explained with Practical Examples

In Python, **scopes** play a critical role in how variables are managed. These scopes can be **local**, **global**, or **nonlocal**. Each of these defines how and where a variable can be accessed or modified.

While the `global` keyword is relatively common, allowing us to modify a global variable from within a function, the `nonlocal` keyword is a bit more specialized. It's used to modify variables in an **enclosing scope** that's neither local nor global.

#### What Does `nonlocal` Do?

The `nonlocal` keyword in Python allows you to **modify a variable in an outer (but non-global) scope** from within a nested function. This is particularly useful in **closures** and other nested function structures.

Without `nonlocal`, Python would treat variables in an enclosing scope as read-only from within a nested function. If you try to reassign a variable without declaring it as `nonlocal`, Python will create a new local variable instead of modifying the one from the outer scope.

### The Scoping Rules in Python

Before diving into how `nonlocal` works, let's quickly revisit Python's scoping rules:

1. **Local scope**: Variables defined within the current function.
2. **Enclosing (nonlocal) scope**: Variables defined in the nearest enclosing function that surrounds the current function.
3. **Global scope**: Variables defined at the top level of a module or script.
4. **Built-in scope**: Special variables that Python predefines in the standard library (e.g., `len`, `range`, etc.).

### When to Use `nonlocal`?

You use `nonlocal` when you want to modify a variable in an enclosing (but not global) scope. It’s often encountered when dealing with **nested functions**, especially **closures**.

Here's an example that illustrates this:

### Example 1: Using `nonlocal` in a Nested Function


def outer_function():
    x = 5 # Variable in the enclosing scope

    def inner_function():
        nonlocal x # Tell Python to use the 'x' from the enclosing scope
        x = 10 # Modify the variable in the enclosing scope

    inner_function()
    print(x)

outer_function() # Outputs: 10


#### Explanation:
1. `x = 5` is declared in `outer_function`, making it an **enclosing variable** for `inner_function`.
2. Inside `inner_function`, we use `nonlocal x`, telling Python that we want to modify the `x` variable in the enclosing scope.
3. After the `inner_function` modifies `x`, the change persists in the outer function.

Without `nonlocal`, Python would have treated `x` inside `inner_function` as a new local variable, and the modification wouldn’t affect the `x` in `outer_function`.

### Why Not Just Use `global`?

You might wonder why we can't just use `global` in these situations. Here’s why:

- `global` allows access to the top-level variables outside all functions.
- `nonlocal`, on the other hand, is for modifying variables that exist in the enclosing scope, but not at the top level.

In most cases, using `nonlocal` is preferable when you're working with nested functions and closures, as it keeps your variables more contained and doesn’t modify the global scope.

### Closures and `nonlocal`

A common scenario for using `nonlocal` is within **closures**. A closure is a function that retains the bindings of the free variables (variables not defined in its local scope) even after the enclosing function has finished executing.

### Example 2: Closure with `nonlocal`


def counter():
    count = 0 # Enclosing variable

    def increment():
        nonlocal count
        count += 1
        return count

    return increment

my_counter = counter()
print(my_counter()) # Outputs: 1
print(my_counter()) # Outputs: 2


#### Explanation:
1. The `counter` function initializes `count` to 0.
2. The `increment` function is a closure that has access to the `count` variable.
3. Using `nonlocal`, the `increment` function modifies the `count` variable in the enclosing `counter` function, so the changes persist across function calls.

Without `nonlocal`, the `count` variable would be reinitialized every time `increment` is called, defeating the purpose of a counter.

### Key Points to Remember

1. **Use `nonlocal` only inside nested functions**: It allows you to modify variables in an enclosing (non-global) scope.
2. **Works with closures**: `nonlocal` is essential when dealing with closures, as it lets you modify variables from the enclosing function.
3. **Prevents unnecessary use of `global`**: Instead of affecting global variables, `nonlocal` keeps changes within a more contained scope.

### When Not to Use `nonlocal`

1. **When you're dealing with global variables**: Use `global` if you need to modify a variable at the module level.
2. **If you don’t need to modify variables**: If you only need to read variables from an outer scope, you don’t need `nonlocal`. Simply access them directly.
3. **For simple use cases**: If your nested function doesn’t modify the enclosing variables or if it doesn’t need to persist state, you may not need to use `nonlocal`.

### Conclusion

The `nonlocal` keyword in Python is a powerful tool for managing variables in nested functions. It allows you to modify variables in an enclosing scope, which is especially useful in closures and when dealing with more complex function structures. By understanding how and when to use `nonlocal`, you can write more efficient, modular, and cleaner code.


Friday, August 16, 2024

Coffee Machine Simulation in Python: Resource Management and User Interaction

Here’s a summary of the coffee machine simulation code:


1. **Constants and Drink Recipes:**
   - **WATER_UNIT, MILK_UNIT, BEANS_UNIT:** These constants represent the basic amounts of water, milk, and coffee beans required to make one drink.
   - **DRINKS Dictionary:** This contains the recipe for each type of drink (espresso, latte, cappuccino), including the price and the required amounts of water, milk, and beans.

2. **State Variables:**
   - **total_water, total_milk, total_beans, total_cups, total_money:** These variables keep track of the machine's current resources and money.

3. **Functions:**

   - **`display_machine_status()`:** Prints the current status of the machine, showing the available water, milk, beans, cups, and money.
   - **`can_make_drink(drink)`:** Checks if the machine has enough resources (water, milk, beans) to make the selected drink.
   - **`make_drink(drink)`:** Deducts the required resources from the machine and adds the drink's price to the total money.
   - **`buy_drink()`:** Prompts the user to select a drink, checks if it can be made, and processes the transaction if possible.
   - **`fill_machine()`:** Allows the user to add water, milk, beans, and cups to the machine.
   - **`take_money()`:** Empties the machine's money into the user's account.
   - **`main_menu()`:** The main loop of the program, where users can choose to buy a drink, fill the machine, take money, display the machine's status, or quit the program.

4. **Main Program:**
   - The `main_menu()` function is called when the program starts, providing a simple text-based interface for interacting with the coffee machine.

---

### **Key Concepts:**

- **Resource Management:** The code keeps track of limited resources (water, milk, beans, cups) and updates them as drinks are made or the machine is refilled.
- **User Interaction:** The user can interact with the machine through a series of text inputs, making it a simple simulation of a real coffee machine.
- **Condition Checking:** The program checks whether there are enough resources before making a drink, ensuring that operations are realistic.

This code provides a clear example of how to manage state and handle user inputs in a simple simulation. It effectively models a coffee machine’s operations, from purchasing drinks to refilling supplies and managing funds.

Featured Post

How HMT Watches Lost the Time: A Deep Dive into Disruptive Innovation Blindness in Indian Manufacturing

The Rise and Fall of HMT Watches: A Story of Brand Dominance and Disruptive Innovation Blindness The Rise and Fal...

Popular Posts