+ (Addition):
In Python, the + operator is primarily used in two main ways: for numeric addition and for sequence concatenation. You can increase the power of your code by leveraging its ability to work consistently across different data types, which makes your code more readable and intuitive.
Uses of the + Operator
The + operator's function changes based on the data types of the operands you use it with.
1. Arithmetic Addition
This is the most common use, as shown in the Canvas. When used with numeric types like integers (int) and floats (float), it performs mathematical addition.
Python
# --- Numeric Addition ---
num1 = 10
num2 = 20.5
result = num1 + num2
print(f"Adding an integer and a float: {result}")
# Output: Adding an integer and a float: 30.5
2. Sequence Concatenation
When used with sequence types like strings (str), lists (list), and tuples (tuple), the + operator joins them together to create a new, single sequence.
Python
# --- String Concatenation ---
first_name = "Rohit"
last_name = "Yadav"
full_name = first_name + " " + last_name
print(f"String Concatenation: {full_name}")
# Output: String Concatenation: Rohit Yadav
# --- List Concatenation ---
list_a = [1, 2, 3]
list_b = [4, 5, 6]
combined_list = list_a + list_b
print(f"List Concatenation: {combined_list}")
# Output: List Concatenation: [1, 2, 3, 4, 5, 6]
How to Increase the Power of Your Code
The power of the + operator lies in its polymorphism—its ability to have different behaviors for different data types. You can leverage this to write more expressive and readable code.
A great way to increase the power of your code is by combining concatenation with type casting (converting one data type to another). This allows you to build dynamic and informative strings from various data sources.
Example: Creating a Dynamic Log Message
Imagine you have data of different types and you want to create a single, formatted log message.
Python
user_id = 101
action = "login"
permissions = ["read", "write"]
timestamp = 2025.08
# Using the '+' operator with type casting to build a powerful, readable string
log_message = "User ID: " + str(user_id) + " performed action: '" + action + "' with permissions: " + str(permissions) + " at " + str(timestamp)
print(log_message)
# Output: User ID: 101 performed action: 'login' with permissions: ['read', 'write'] at 2025.08
In this example, the + operator is used multiple times to concatenate strings. By converting the integer user_id, the list permissions, and the float timestamp to strings using str(), you can seamlessly combine them into a single, coherent message. This is a much more powerful and flexible approach than just adding numbers.
The __add__ method defines what should happen when the + operator is used between two instances of your class. The method should combine the attributes of the two objects and return a new object representing the combined result.
How It Works
1. Define the __add__(self, other) Method: Inside your class, you create this special method. self refers to the object on the left of the +, and other refers to the object on the right.
2. Combine Attributes: You write the logic to merge the data from self and other. For lists of items, using a set is a great way to automatically handle duplicates.
3. Return a New Instance: The method must create and return a brand new instance of your class, initialized with the combined data. This ensures that the original objects are not modified.
# --- 1. Define the Custom Class ---
class ShoppingList:
"""A simple class representing a shopping list."""
def __init__(self, owner, items):
"""
The constructor for the class.
Initializes the shopping list with an owner and a list of items.
"""
self.owner = owner
self.items = list(items)
def __repr__(self):
"""
Provides a developer-friendly string representation of the object,
which is useful for printing and debugging.
"""
return f"ShoppingList(owner='{self.owner}', items={self.items})"
def __add__(self, other):
"""
This is the special method that defines the behavior of the '+' operator.
It combines this shopping list with another one.
"""
# First, check if the 'other' object is also an instance of ShoppingList.
# This prevents errors if you try to add, for example, a number to a list.
if not isinstance(other, ShoppingList):
return NotImplemented
# Combine the owners' names for the new list.
combined_owner = f"{self.owner} & {other.owner}"
# Combine the item lists.
# We use a set to automatically handle any duplicate items between the two lists,
# and then convert it back to a list.
combined_items = list(set(self.items + other.items))
# Create and return a *new* ShoppingList object with the combined data.
return ShoppingList(combined_owner, combined_items)
# --- 2. Create Instances of the Class ---
# Create two separate shopping lists for two different people.
Rohits_list = ShoppingList("Rohit", ["milk", "bread", "eggs"])
Nehas_list = ShoppingList("Neha", ["bread", "butter", "jam"])
print("--- Original Objects ---")
print(Rohits_list)
print(Nehas_list)
# --- 3. Use the '+' Operator to Combine the Objects ---
# Because we defined the __add__ method, we can now use the '+' operator
# to "concatenate" our two ShoppingList objects.
combined_shopping_list = Rohits_list + Nehas_list
print("\n--- Combined Object Bundle ---")
print(combined_shopping_list)
# --- 4. Verify the Original Objects are Unchanged ---
# The '+' operation created a new object and did not modify the originals.
print("\n--- Originals Unchanged ---")
print(Rohits_list)
print(Nehas_list)
- (Subtraction)
In Python, the - operator has three main uses: numeric subtraction, unary negation, and set difference. You can dramatically increase the power and readability of your code by using this operator for set operations and by defining its behavior for your own custom classes.
1. Numeric Subtraction and Unary Negation
This is the most common and straightforward use. For numeric types like integers (int) and floats (float), it performs mathematical subtraction. It can also be used as a unary operator to negate a number's sign.
Python
# Standard subtraction
remaining_balance = 100.75 - 25.50
print(f"Remaining Balance: {remaining_balance}") # Output: 75.25
# Unary negation to change the sign
positive_number = 50
negative_number = -positive_number
print(f"Negative Number: {negative_number}") # Output: -50
2. Set Difference
This is a very powerful feature. When used with sets, the - operator performs a difference operation. It creates a new set containing all the items that are in the first set but not in the second set.
This is an incredibly efficient way to find unique elements between two collections.
Python
# --- Finding the difference between two sets ---
required_skills = {"Python", "SQL", "Git", "Docker"}
candidate_skills = {"Python", "Git", "Java"}
# Find which skills the candidate is missing
missing_skills = required_skills - candidate_skills
print(f"Missing skills: {missing_skills}")
# Output: Missing skills: {'Docker', 'SQL'}
3. Increasing Power with Operator Overloading (__sub__)
Just like you saw with the __add__ method in the Canvas, you can define the behavior of the - operator for your own custom classes by implementing the __sub__ special method. This allows you to create intuitive and readable logic for your objects.
Example: A Budget Class
Imagine you have a Budget class that tracks income and expenses. You can define the - operator to calculate the difference between two budgets, showing how much more was spent in one compared to the other.
Python
class Budget:
"""A class to represent a simple budget."""
def __init__(self, name, income, expenses):
self.name = name
self.income = income
self.expenses = expenses
self.net = income - expenses
def __repr__(self):
return f"Budget(name='{self.name}', net={self.net})"
def __sub__(self, other):
"""Defines the behavior of the '-' operator for Budget objects."""
if not isinstance(other, Budget):
return NotImplemented
# Calculate the difference in income and expenses
income_diff = self.income - other.income
expense_diff = self.expenses - other.expenses
# Create a new "Difference" object to represent the result
return Budget(f"Difference ({self.name} - {other.name})", income_diff, expense_diff)
# Create two budget objects
january_budget = Budget("January", 5000, 4000)
february_budget = Budget("February", 5200, 4500)
print(f"January Budget: {january_budget}")
print(f"February Budget: {february_budget}")
# Use the '-' operator on our custom objects
budget_difference = january_budget - february_budget
print(f"\nBudget Difference: {budget_difference}")
# Output: Budget(name='Difference (January - February)', net=-300)
# This shows that in January, income was 200 less and expenses were 500 less than in February,
# resulting in a net difference of -300.
By implementing __sub__, you make your code more expressive. The line january_budget - february_budget is much clearer and more powerful than calling a custom method like january_budget.calculate_difference(february_budget).
* (Multiplication)
In Python, the * operator is primarily used in two ways: for numeric multiplication and for sequence repetition. You can significantly increase the power of your code by using it for concise data initialization and by defining its behavior for your own custom classes to create highly readable, domain-specific logic.
1. Numeric Multiplication
This is the most common use. For numeric types like integers (int) and floats (float), it performs standard mathematical multiplication.
Python
# --- Numeric Multiplication ---
item_price = 150.50
quantity = 4
total_cost = item_price * quantity
print(f"Total Cost: {total_cost}")
# Output: Total Cost: 601.0
2. Sequence Repetition
This is a powerful and concise feature of Python. When used with sequence types like strings (str), lists (list), and tuples (tuple), the * operator creates a new sequence by repeating the original's elements a specified number of times.
This is extremely useful for initializing data structures.
Python
# --- String Repetition ---
separator = "=" * 20
print(separator)
# Output: ====================
# --- List Repetition (Powerful for initialization) ---
# Create a list with ten zeros
initial_scores = [0] * 10
print(f"Initialized Scores: {initial_scores}")
# Output: Initialized Scores: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3. Increasing Power with Operator Overloading (__mul__)
Just as the __add__ method in your Canvas code defines the + operator, you can define the behavior of the * operator for your custom classes by implementing the __mul__ special method. This allows you to create intuitive logic that reads like plain English.
Example: Scaling a ShoppingList
Let's extend the ShoppingList class from your Canvas. What if you wanted to represent buying multiple sets of the same shopping list for a party? You can define the * operator to do just that.
Python
class ShoppingList:
"""A simple class representing a shopping list."""
def __init__(self, owner, items):
self.owner = owner
self.items = list(items)
def __repr__(self):
return f"ShoppingList(owner='{self.owner}', items={self.items})"
def __mul__(self, multiplier):
"""Defines the behavior of the '*' operator for ShoppingList objects."""
# Ensure the multiplier is an integer
if not isinstance(multiplier, int):
return NotImplemented
# Create a new owner name for the scaled list
scaled_owner = f"{self.owner} (x{multiplier})"
# Repeat the items in the list by the multiplier
scaled_items = self.items * multiplier
# Return a new ShoppingList object with the scaled data
return ShoppingList(scaled_owner, scaled_items)
# Create a base shopping list for one person
party_guest_list = ShoppingList("Guest", ["chips", "soda"])
print(f"List for one guest: {party_guest_list}")
# Use the '*' operator to create a list for 5 guests
party_supply_list = party_guest_list * 5
print(f"\nList for five guests: {party_supply_list}")
# Output: ShoppingList(owner='Guest (x5)', items=['chips', 'soda', 'chips', 'soda', 'chips', 'soda', 'chips', 'soda', 'chips', 'soda'])
By implementing __mul__, you make your code far more expressive. The line party_guest_list * 5 is a powerful and intuitive way to represent a real-world concept, making your code easier to read and understand than a more verbose method call like party_guest_list.scale_for_guests(5).
/ (Division): Always results in a float.
In Python, the division operator / has a primary, specific function, but its power can be greatly expanded for custom objects.
The / operator is used in two main ways in Python:
1. True Division (/): This is the standard division operator. It performs a mathematical division and always returns a float (a number with a decimal), even if the numbers divide evenly.
2. Floor Division (//): This operator performs division and then rounds the result down to the nearest whole number, always returning an int if the operands are integers.
You can increase the power of your code by defining the behavior of the / operator for your own custom classes. This is done by implementing the __truediv__ special method, a technique known as operator overloading. This allows you to create highly intuitive and readable logic for your objects.
Example: Scaling a Recipe Class
Imagine you have a Recipe class that holds ingredients and their quantities for a certain number of servings. The most intuitive way to scale this recipe down to serve fewer people would be to "divide" it. By implementing __truediv__, you can make this logic work directly with the / operator.
# --- 1. Define the Custom Class ---
class Recipe:
"""A class to represent a recipe with ingredients and servings."""
def __init__(self, name, servings, ingredients):
"""
The constructor for the class.
Initializes the recipe with a name, number of servings, and a
dictionary of ingredients and their quantities.
"""
self.name = name
self.servings = servings
self.ingredients = ingredients
def __repr__(self):
"""
Provides a developer-friendly string representation of the object.
"""
return (f"Recipe(name='{self.name}', servings={self.servings}, "
f"ingredients={self.ingredients})")
def __truediv__(self, divisor):
"""
This is the special method that defines the behavior of the '/' operator.
It scales the recipe down by the divisor.
"""
# Ensure we are dividing by a number (int or float).
if not isinstance(divisor, (int, float)):
return NotImplemented
if divisor <= 0:
raise ValueError("Cannot divide a recipe by zero or a negative number.")
# Calculate the new number of servings.
new_servings = self.servings / divisor
# Scale down each ingredient's quantity.
scaled_ingredients = {
ingredient: quantity / divisor
for ingredient, quantity in self.ingredients.items()
}
# Create a new name for the scaled recipe.
new_name = f"{self.name} (scaled for {new_servings:.1f} servings)"
# Return a *new* Recipe object with the scaled-down data.
return Recipe(new_name, new_servings, scaled_ingredients)
# --- 2. Create an Instance of the Class ---
# A recipe for a cake that serves 8 people.
chocolate_cake_recipe = Recipe(
name="Chocolate Cake",
servings=8,
ingredients={"flour_grams": 200, "sugar_grams": 150, "eggs": 4}
)
print("--- Original Recipe ---")
print(chocolate_cake_recipe)
# --- 3. Use the '/' Operator to Scale the Object ---
# Now, let's scale this recipe down to serve only 2 people.
# This is intuitive: we are dividing the 8-serving recipe by 4.
small_cake_recipe = chocolate_cake_recipe / 4
print("\n--- Scaled-Down Recipe ---")
print(small_cake_recipe)
# --- 4. Verify the Original Object is Unchanged ---
# The '/' operation created a new object and did not modify the original.
print("\n--- Original Unchanged ---")
print(chocolate_cake_recipe)
// (Floor Division): Divides and rounds down to the nearest whole number.
In Python, the // (Floor Division) operator is used in two main ways: for numeric floor division and for creating custom logic for your own classes through operator overloading. You can increase the power of your code by using this operator to create intuitive, domain-specific logic that makes your classes easier to work with.
1. Numeric Floor Division
This is the standard use of the // operator. It performs division and then rounds the result down to the nearest whole number.
- With positive numbers, it behaves like truncating the decimal.
- With negative numbers, it rounds away from zero (e.g., -10 // 3 is -4).
Python
# --- Numeric Floor Division ---
print(f"10 // 3 = {10 // 3}")
# Output: 10 // 3 = 3
print(f"10.5 // 3 = {10.5 // 3}")
# Output: 10.5 // 3 = 3.0 (result is a float if one operand is a float)
print(f"-10 // 3 = {-10 // 3}")
# Output: -10 // 3 = -4
2. Increasing Power with Operator Overloading (__floordiv__)
You can define the behavior of the // operator for your own custom classes by implementing the __floordiv__ special method. This allows you to assign a powerful and intuitive meaning to the operator that is specific to your class's logic.
Example: Scaling a Recipe Class Based on a Key Ingredient
Let's extend the Recipe class from your Canvas. Imagine you have a certain amount of a key ingredient, and you want to know the largest whole-number recipe you can make. The // operator is perfect for this "how many times does this fit completely?" logic.
We can define recipe // ingredient_tuple to calculate the maximum number of servings you can make based on the amount of a single ingredient you have.
# --- 1. Define the Custom Class ---
class Recipe:
"""A class to represent a recipe with ingredients and servings."""
def __init__(self, name, servings, ingredients):
"""
The constructor for the class.
Initializes the recipe with a name, number of servings, and a
dictionary of ingredients and their quantities.
"""
self.name = name
self.servings = servings
self.ingredients = ingredients
def __repr__(self):
"""
Provides a developer-friendly string representation of the object.
"""
return (f"Recipe(name='{self.name}', servings={self.servings}, "
f"ingredients={self.ingredients})")
def __truediv__(self, divisor):
"""
Defines the behavior of the '/' operator (true division).
It scales the recipe down by the divisor.
"""
if not isinstance(divisor, (int, float)):
return NotImplemented
if divisor <= 0:
raise ValueError("Cannot divide a recipe by zero or a negative number.")
new_servings = self.servings / divisor
scaled_ingredients = {ing: qty / divisor for ing, qty in self.ingredients.items()}
new_name = f"{self.name} (scaled for {new_servings:.1f} servings)"
return Recipe(new_name, new_servings, scaled_ingredients)
def __floordiv__(self, ingredient_tuple):
"""
This is the special method that defines the behavior of the '//' operator.
It calculates the largest whole-number recipe you can make based on a
limited quantity of a key ingredient.
"""
# Ensure the right-hand side is a tuple of (ingredient_name, available_quantity)
if not isinstance(ingredient_tuple, tuple) or len(ingredient_tuple) != 2:
return NotImplemented
ingredient_name, available_quantity = ingredient_tuple
# Check if the ingredient is in the recipe
if ingredient_name not in self.ingredients:
raise ValueError(f"Ingredient '{ingredient_name}' not found in the recipe.")
# Get the required quantity for the original recipe
required_quantity_per_recipe = self.ingredients[ingredient_name]
# Calculate how many full recipes can be made
num_recipes = available_quantity // required_quantity_per_recipe
# Scale the original recipe by this whole number
return self / (self.servings / num_recipes) if num_recipes > 0 else Recipe(f"Cannot make {self.name}", 0, {})
# --- 2. Create an Instance of the Class ---
# A recipe for a cake that serves 8 people and requires 200g of flour.
chocolate_cake_recipe = Recipe(
name="Chocolate Cake",
servings=8,
ingredients={"flour_grams": 200, "sugar_grams": 150, "eggs": 4}
)
print("--- Original Recipe ---")
print(chocolate_cake_recipe)
# --- 3. Use the '//' Operator for a Powerful Calculation ---
# I have 550g of flour. How many full servings of cake can I make?
# The logic is: 550g // 200g_per_recipe = 2 full recipes.
# 2 recipes * 8 servings/recipe = 16 servings.
# So we should get a recipe scaled for 16 servings.
available_flour = ("flour_grams", 550)
scaled_recipe = chocolate_cake_recipe // available_flour
print(f"\n--- Recipe scaled based on having {available_flour[1]}g of flour ---")
print(scaled_recipe)
% (Modulus): Returns the remainder of a division.
In Python, the % (Modulus) operator is used in three main ways: for numeric remainder, for old-style string formatting, and for powerful custom logic in your own classes through operator overloading.
You can increase the power of your code by using this operator to create intuitive, domain-specific logic that makes your classes more readable and easier to use.
1. Numeric Remainder (Modulus)
This is the most common use of the % operator. It performs a division operation and returns the remainder. It's incredibly useful for tasks like checking if a number is even or odd, or for cycling through a sequence of numbers.
Python
# --- Numeric Remainder ---
print(f"10 % 3 = {10 % 3}")
# Output: 1 (because 10 divided by 3 is 3 with a remainder of 1)
# A common use case: checking for even or odd numbers
number = 15
if number % 2 == 0:
print(f"{number} is even.")
else:
print(f"{number} is odd.")
# Output: 15 is odd.
2. Old-Style String Formatting
Before the introduction of .format() and f-strings, the % operator was the primary way to format strings in Python. It works by substituting %s (for strings), %d (for integers), and %f (for floats) placeholders with values. While you will still see this in older code, modern f-strings are now preferred.
Python
# --- Old-Style String Formatting ---
name = "Neha"
age = 29
print("My name is %s and I am %d years old." % (name, age))
# Output: My name is Neha and I am 29 years old.
3. Increasing Power with Operator Overloading (__mod__)
You can define the behavior of the % operator for your own custom classes by implementing the __mod__ special method. This allows you to assign a powerful and intuitive meaning to the "remainder" operation that is specific to your class's logic.
Example: Calculating Leftover Ingredients in a Recipe
Let's extend the Recipe class from your Canvas. What if you want to make several smaller portions from a large batch recipe and need to know what ingredients will be left over? The % (modulus/remainder) operator is conceptually perfect for this.
We can define recipe % portion_size to calculate the leftover ingredients after making as many full portions as possible.
Python
class Recipe:
"""A class to represent a recipe with ingredients and servings."""
def __init__(self, name, servings, ingredients):
self.name = name
self.servings = servings
self.ingredients = ingredients
def __repr__(self):
return (f"Recipe(name='{self.name}', servings={self.servings}, "
f"ingredients={self.ingredients})")
def __mod__(self, portion_size):
"""
This is the special method that defines the behavior of the '%' operator.
It calculates the leftover ingredients after creating as many full portions
of a given size as possible.
"""
if not isinstance(portion_size, (int, float)):
return NotImplemented
if portion_size <= 0:
raise ValueError("Portion size must be positive.")
# Calculate how many full portions can be made
num_portions = self.servings // portion_size
# Calculate the total servings used by the full portions
servings_used = num_portions * portion_size
# Calculate the number of leftover servings
leftover_servings = self.servings % portion_size
# Calculate the leftover ingredients
leftover_ingredients = {
ingredient: quantity * (leftover_servings / self.servings)
for ingredient, quantity in self.ingredients.items()
}
# Return a new Recipe object representing the leftovers
return Recipe(f"Leftovers from {self.name}", leftover_servings, leftover_ingredients)
# --- Create an Instance of the Class ---
# A large batch recipe for soup that serves 10 people.
large_soup_recipe = Recipe(
name="Large Batch Soup",
servings=10,
ingredients={"carrots": 500, "potatoes": 800, "stock_ml": 2000}
)
print("--- Original Batch Recipe ---")
print(large_soup_recipe)
# --- Use the '%' Operator for a Powerful Calculation ---
# I want to pack this soup into portions that serve 3 people each.
# What will be left over?
# Logic: 10 servings % 3_servings_per_portion = 1 leftover serving.
leftovers = large_soup_recipe % 3
print(f"\n--- Leftovers after making 3-serving portions ---")
print(leftovers)
# Output: Recipe(name='Leftovers from Large Batch Soup', servings=1.0, ingredients={'carrots': 50.0, 'potatoes': 80.0, 'stock_ml': 200.0})
** (Exponentiation): Raises a number to the power of another.
In Python, the ** (Exponentiation) operator is used in two main ways: for numeric exponentiation and for creating powerful, custom logic for your own classes through operator overloading.
You can dramatically increase the power and readability of your code by defining the behavior of this operator for your own objects, allowing you to express complex, domain-specific concepts in a very intuitive way.
1. Numeric Exponentiation
This is the standard mathematical use of the ** operator. It raises a number to the power of another.
Python
# --- Numeric Exponentiation ---
print(f"3 ** 4 = {3 ** 4}")
# Output: 81 (which is 3 * 3 * 3 * 3)
print(f"5.0 ** 2 = {5.0 ** 2}")
# Output: 25.0
2. Increasing Power with Operator Overloading (__pow__)
You can define the behavior of the ** operator for your own custom classes by implementing the __pow__ special method. This allows you to assign a powerful and intuitive meaning to the "power" operation that is specific to your class's logic.
Example: Creating an "Intensified" Recipe
Let's extend the Recipe class from your Canvas. What if you wanted to create a "double-strength" or "triple-strength" version of a recipe? For example, a "double-strength" cake might have double the base ingredients but four times the flavoring (like cocoa), making it richer. The ** operator is conceptually perfect for this "intensifying" logic.
We can define recipe ** intensity_factor to create a new, more intense version of the recipe.
# --- 1. Define the Custom Class ---
class Recipe:
"""
A class to represent a recipe with ingredients, servings, and ingredient types.
"""
def __init__(self, name, servings, ingredients):
"""
The constructor for the class.
Ingredients is a dictionary where each value is another dictionary
specifying the quantity and type ('base' or 'flavor').
"""
self.name = name
self.servings = servings
self.ingredients = ingredients
def __repr__(self):
"""
Provides a developer-friendly string representation of the object.
"""
return (f"Recipe(name='{self.name}', servings={self.servings}, "
f"ingredients={self.ingredients})")
def __pow__(self, intensity_factor):
"""
This is the special method that defines the behavior of the '**' operator.
It "intensifies" the recipe. Base ingredients are scaled linearly,
while flavor ingredients are scaled exponentially.
"""
if not isinstance(intensity_factor, (int, float)):
return NotImplemented
if intensity_factor < 0:
raise ValueError("Intensity factor cannot be negative.")
# Create a new name for the intensified recipe.
new_name = f"{self.name} (Intensity x{intensity_factor})"
# The number of servings can scale linearly.
new_servings = self.servings * intensity_factor
# Scale the ingredients based on their type.
intensified_ingredients = {}
for ingredient, details in self.ingredients.items():
quantity = details['quantity']
ing_type = details['type']
if ing_type == 'flavor':
# Flavor ingredients are scaled exponentially
new_quantity = quantity * (intensity_factor ** 2)
else: # 'base' ingredients
# Base ingredients are scaled linearly
new_quantity = quantity * intensity_factor
intensified_ingredients[ingredient, ing_type] = {'quantity': new_quantity, 'type': ing_type}
# A bug fix: The key should be just the ingredient name.
intensified_ingredients[ingredient] = {'quantity': new_quantity, 'type': ing_type}
# Return a *new* Recipe object with the intensified data.
return Recipe(new_name, new_servings, intensified_ingredients)
# --- 2. Create an Instance of the Class ---
# A recipe for a spicy curry.
spicy_curry_recipe = Recipe(
name="Spicy Curry",
servings=4,
ingredients={
"chicken_grams": {"quantity": 500, "type": "base"},
"rice_grams": {"quantity": 300, "type": "base"},
"chili_powder_tsp": {"quantity": 2, "type": "flavor"},
"turmeric_tsp": {"quantity": 1, "type": "flavor"}
}
)
print("--- Original Recipe ---")
print(spicy_curry_recipe)
# --- 3. Use the '**' Operator for a Powerful Calculation ---
# Let's create a "double-strength" version of this recipe for a party.
# We expect the base ingredients to double, but the flavor ingredients to quadruple.
double_strength_curry = spicy_curry_recipe ** 2
print(f"\n--- Recipe at Intensity x2 ---")
print(double_strength_curry)