Prerequisites
- Basic understanding of programming concepts ๐
- Python installation (3.8+) ๐
- VS Code or preferred IDE ๐ป
What you'll learn
- Understand the concept fundamentals ๐ฏ
- Apply the concept in real projects ๐๏ธ
- Debug common issues ๐
- Write clean, Pythonic code โจ
๐ฏ Introduction
Welcome to this exciting tutorial on the self
parameter! ๐ Have you ever wondered why Python methods always seem to have that mysterious self
as their first parameter? Today, weโre going to demystify this essential concept thatโs at the heart of object-oriented programming in Python!
Youโll discover how self
acts as your instanceโs personal ID card ๐ชช, allowing each object to keep track of its own data and behavior. Whether youโre building game characters ๐ฎ, managing user accounts ๐ค, or creating shopping systems ๐, understanding self
is essential for writing robust, object-oriented Python code.
By the end of this tutorial, youโll confidently use self
like a Python pro! Letโs dive in! ๐โโ๏ธ
๐ Understanding the self Parameter
๐ค What is self?
The self
parameter is like your objectโs personal pronoun - itโs how an instance refers to itself! ๐ช Think of it as a name tag that says โHey, this is ME!โ whenever an object needs to access its own attributes or methods.
In Python terms, self
is a reference to the current instance of a class. This means you can:
- โจ Access instance attributes unique to each object
- ๐ Call other methods within the same instance
- ๐ก๏ธ Keep data separate between different instances
๐ก Why Use self?
Hereโs why self
is absolutely essential:
- Instance Isolation ๐: Each object keeps its own data separate
- Method Access ๐ป: Call other methods from within your class
- State Management ๐: Track and modify object state over time
- Clarity ๐ง: Makes it clear when youโre accessing instance data
Real-world example: Imagine building a game with multiple players ๐ฎ. With self
, each player can have their own health, score, and inventory without interfering with other players!
๐ง Basic Syntax and Usage
๐ Simple Example
Letโs start with a friendly example:
# ๐ Hello, self!
class Dog:
def __init__(self, name, breed):
# ๐จ Using self to store instance data
self.name = name # ๐ Dog's name
self.breed = breed # ๐ฆด Dog's breed
self.tricks = [] # ๐ฏ List of tricks
def bark(self):
# ๐ฌ Using self to access instance data
return f"{self.name} says: Woof! ๐"
def learn_trick(self, trick):
# โจ Modifying instance data with self
self.tricks.append(trick)
print(f"{self.name} learned {trick}! ๐")
# ๐ฎ Let's create some dogs!
buddy = Dog("Buddy", "Golden Retriever")
max = Dog("Max", "Beagle")
print(buddy.bark()) # Buddy says: Woof! ๐
print(max.bark()) # Max says: Woof! ๐
๐ก Explanation: Notice how self
allows each dog to have its own name and tricks! When we call buddy.bark()
, Python automatically passes buddy
as the self
parameter.
๐ฏ Common Patterns
Here are patterns youโll use daily:
# ๐๏ธ Pattern 1: Initializing instance attributes
class Player:
def __init__(self, username):
self.username = username # ๐ค Player's name
self.level = 1 # ๐ Starting level
self.health = 100 # โค๏ธ Full health
self.inventory = [] # ๐ Empty backpack
# ๐จ Pattern 2: Accessing and modifying attributes
class BankAccount:
def __init__(self, initial_balance=0):
self.balance = initial_balance # ๐ฐ Starting money
def deposit(self, amount):
self.balance += amount # ๐ต Add money
return f"New balance: ${self.balance} ๐ฐ"
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount # ๐ธ Remove money
return f"Withdrew ${amount}. Balance: ${self.balance}"
return "Insufficient funds! ๐
"
# ๐ Pattern 3: Methods calling other methods
class Calculator:
def __init__(self):
self.result = 0 # ๐ข Current result
def add(self, number):
self.result += number
return self
def multiply(self, number):
self.result *= number
return self
def get_result(self):
return f"Result: {self.result} ๐ฏ"
# ๐ Method chaining!
calc = Calculator()
print(calc.add(5).multiply(3).get_result()) # Result: 15 ๐ฏ
๐ก Practical Examples
๐ Example 1: Shopping Cart System
Letโs build something real:
# ๐๏ธ A complete shopping cart system
class Product:
def __init__(self, name, price, emoji):
self.name = name # ๐ฆ Product name
self.price = price # ๐ต Product price
self.emoji = emoji # ๐จ Product emoji
def display(self):
return f"{self.emoji} {self.name} - ${self.price:.2f}"
class ShoppingCart:
def __init__(self, customer_name):
self.customer_name = customer_name # ๐ค Who's shopping
self.items = [] # ๐ Cart items
self.discount = 0 # ๐ซ Discount percentage
def add_item(self, product, quantity=1):
# โ Add products to cart
for _ in range(quantity):
self.items.append(product)
print(f"Added {quantity}x {product.emoji} {product.name} to cart!")
return self # ๐ Enable method chaining
def remove_item(self, product_name):
# โ Remove item from cart
for item in self.items:
if item.name == product_name:
self.items.remove(item)
print(f"Removed {item.emoji} {item.name} from cart!")
return self
print(f"Item '{product_name}' not found in cart! ๐ค")
return self
def apply_discount(self, percentage):
# ๐ Apply discount
self.discount = percentage
print(f"Applied {percentage}% discount! ๐ธ")
return self
def calculate_total(self):
# ๐ฐ Calculate total with discount
subtotal = sum(item.price for item in self.items)
discount_amount = subtotal * (self.discount / 100)
total = subtotal - discount_amount
return total
def checkout(self):
# ๐ Display cart and checkout
print(f"\n๐ {self.customer_name}'s Shopping Cart:")
print("-" * 40)
# Group items for display
item_counts = {}
for item in self.items:
key = item.name
if key in item_counts:
item_counts[key]['count'] += 1
else:
item_counts[key] = {
'product': item,
'count': 1
}
# Display grouped items
for item_data in item_counts.values():
product = item_data['product']
count = item_data['count']
total_price = product.price * count
print(f" {product.emoji} {product.name} x{count} = ${total_price:.2f}")
print("-" * 40)
subtotal = sum(item.price for item in self.items)
print(f"Subtotal: ${subtotal:.2f}")
if self.discount > 0:
discount_amount = subtotal * (self.discount / 100)
print(f"Discount ({self.discount}%): -${discount_amount:.2f}")
total = self.calculate_total()
print(f"Total: ${total:.2f} ๐ณ")
print(f"\nThank you for shopping, {self.customer_name}! ๐")
# ๐ฎ Let's go shopping!
# Create products
laptop = Product("Gaming Laptop", 1299.99, "๐ป")
mouse = Product("Wireless Mouse", 49.99, "๐ฑ๏ธ")
keyboard = Product("Mechanical Keyboard", 149.99, "โจ๏ธ")
headset = Product("Gaming Headset", 89.99, "๐ง")
# Shop!
cart = ShoppingCart("Sarah")
cart.add_item(laptop).add_item(mouse, 2).add_item(keyboard).apply_discount(10)
cart.checkout()
๐ฏ Try it yourself: Add a save_for_later
method that moves items to a wishlist!
๐ฎ Example 2: RPG Character System
Letโs make it fun with a game character system:
# ๐ RPG character with self-managed stats
class RPGCharacter:
def __init__(self, name, character_class):
# ๐ฏ Initialize character stats
self.name = name # ๐ค Character name
self.character_class = character_class # โ๏ธ Class (Warrior, Mage, etc.)
self.level = 1 # ๐ Starting level
self.experience = 0 # โญ Experience points
self.health = 100 # โค๏ธ Current health
self.max_health = 100 # ๐ Maximum health
self.mana = 50 # ๐ Magic points
self.max_mana = 50 # ๐ Maximum mana
self.skills = [] # ๐ฏ Learned skills
self.inventory = [] # ๐ Items
self.gold = 0 # ๐ฐ Currency
# ๐จ Class-specific bonuses
self._apply_class_bonuses()
def _apply_class_bonuses(self):
# ๐ก๏ธ Different classes get different stats
if self.character_class == "Warrior":
self.max_health = 150
self.health = 150
self.skills.append("โ๏ธ Sword Strike")
elif self.character_class == "Mage":
self.max_mana = 100
self.mana = 100
self.skills.append("๐ฅ Fireball")
elif self.character_class == "Rogue":
self.gold = 50 # Rogues start with gold!
self.skills.append("๐ก๏ธ Sneak Attack")
def gain_experience(self, amount):
# โญ Level up system
self.experience += amount
print(f"{self.name} gained {amount} XP! โจ")
# Check for level up
while self.experience >= self.level * 100:
self.experience -= self.level * 100
self._level_up()
def _level_up(self):
# ๐ Level up rewards
self.level += 1
old_health = self.max_health
old_mana = self.max_mana
self.max_health += 20
self.max_mana += 10
self.health = self.max_health # Full heal on level up!
self.mana = self.max_mana
print(f"\n๐ LEVEL UP! {self.name} is now level {self.level}!")
print(f" โค๏ธ Health: {old_health} โ {self.max_health}")
print(f" ๐ Mana: {old_mana} โ {self.max_mana}")
# Learn new skills at certain levels
if self.level == 5:
self._learn_skill("๐ช Power Strike" if self.character_class == "Warrior"
else "โ๏ธ Ice Shard" if self.character_class == "Mage"
else "๐จ Vanish")
def _learn_skill(self, skill):
# ๐ฏ Learn new abilities
self.skills.append(skill)
print(f" ๐ Learned new skill: {skill}")
def use_skill(self, skill_index):
# ๐ฎ Use abilities
if 0 <= skill_index < len(self.skills):
skill = self.skills[skill_index]
print(f"{self.name} uses {skill}! ๐ฅ")
# Deduct mana for magic skills
if "๐ฅ" in skill or "โ๏ธ" in skill:
self.mana = max(0, self.mana - 20)
print(f" ๐ Mana: {self.mana}/{self.max_mana}")
else:
print("Invalid skill! ๐
")
def add_item(self, item):
# ๐ Inventory management
self.inventory.append(item)
print(f"{self.name} found {item}! ๐")
def show_status(self):
# ๐ Display character sheet
print(f"\n{'='*40}")
print(f"๐ฎ {self.name} - Level {self.level} {self.character_class}")
print(f"{'='*40}")
print(f"โค๏ธ Health: {self.health}/{self.max_health}")
print(f"๐ Mana: {self.mana}/{self.max_mana}")
print(f"โญ Experience: {self.experience}/{self.level * 100}")
print(f"๐ฐ Gold: {self.gold}")
print(f"๐ฏ Skills: {', '.join(self.skills)}")
if self.inventory:
print(f"๐ Inventory: {', '.join(self.inventory)}")
print(f"{'='*40}\n")
# ๐ฎ Let's play!
hero = RPGCharacter("Aragorn", "Warrior")
mage = RPGCharacter("Gandalf", "Mage")
# Adventure time!
hero.show_status()
hero.gain_experience(250) # Level up!
hero.add_item("๐ก๏ธ Steel Sword")
hero.add_item("๐ก๏ธ Iron Shield")
hero.use_skill(0) # Use first skill
hero.show_status()
# Mage's turn
mage.gain_experience(150)
mage.use_skill(0) # Cast Fireball
๐ Advanced Concepts
๐งโโ๏ธ Advanced Topic 1: self in Class Methods vs Static Methods
When youโre ready to level up, understand the different method types:
# ๐ฏ Advanced method types
class AdvancedExample:
company_name = "TechCorp" # ๐ข Class variable
def __init__(self, employee_name):
self.name = employee_name # ๐ค Instance variable
# ๐จ Regular instance method (uses self)
def introduce(self):
return f"Hi, I'm {self.name} from {self.company_name}! ๐"
# ๐๏ธ Class method (uses cls instead of self)
@classmethod
def change_company(cls, new_name):
old_name = cls.company_name
cls.company_name = new_name
return f"Company renamed from {old_name} to {new_name}! ๐ข"
# ๐ง Static method (no self or cls)
@staticmethod
def company_motto():
return "Innovation through code! ๐"
# ๐ช Property with self
@property
def email(self):
return f"{self.name.lower().replace(' ', '.')}@{self.company_name.lower()}.com"
# ๐ฎ Using different method types
emp1 = AdvancedExample("Sarah Johnson")
emp2 = AdvancedExample("Mike Chen")
print(emp1.introduce()) # Uses self
print(emp1.email) # Property using self
print(AdvancedExample.change_company("SuperTech")) # Class method
print(emp2.introduce()) # Now shows new company name!
print(AdvancedExample.company_motto()) # Static method
๐๏ธ Advanced Topic 2: self in Inheritance
For the brave developers exploring inheritance:
# ๐ Inheritance and self
class Vehicle:
def __init__(self, brand, model):
self.brand = brand # ๐ท๏ธ Vehicle brand
self.model = model # ๐ Vehicle model
self.is_running = False # ๐ Engine status
def start_engine(self):
self.is_running = True
return f"{self.brand} {self.model} engine started! ๐"
def stop_engine(self):
self.is_running = False
return f"{self.brand} {self.model} engine stopped! ๐"
class ElectricCar(Vehicle):
def __init__(self, brand, model, battery_capacity):
# ๐ฏ Call parent's __init__ using super()
super().__init__(brand, model)
self.battery_capacity = battery_capacity # ๐ kWh
self.battery_level = 100 # ๐ Percentage
def start_engine(self):
# ๐ Override parent method but still use self
if self.battery_level > 0:
self.is_running = True
return f"{self.brand} {self.model} silently powered on! โก"
return f"Battery dead! Please charge your {self.model}! ๐"
def charge(self, hours):
# โก Unique method for electric cars
charge_rate = 20 # 20% per hour
self.battery_level = min(100, self.battery_level + (hours * charge_rate))
return f"Charged to {self.battery_level}%! ๐"
def drive(self, distance):
# ๐ Driving depletes battery
if not self.is_running:
return "Start the car first! ๐"
battery_used = distance * 0.5 # 0.5% per km
if battery_used <= self.battery_level:
self.battery_level -= battery_used
return f"Drove {distance}km. Battery: {self.battery_level:.1f}% ๐"
else:
max_distance = self.battery_level / 0.5
self.battery_level = 0
self.is_running = False
return f"Only drove {max_distance:.1f}km before battery died! ๐
"
# ๐ฎ Test drive!
tesla = ElectricCar("Tesla", "Model 3", 75)
print(tesla.start_engine())
print(tesla.drive(50))
print(tesla.drive(150)) # Battery dies!
print(tesla.charge(3)) # Charge for 3 hours
print(tesla.start_engine())
โ ๏ธ Common Pitfalls and Solutions
๐ฑ Pitfall 1: Forgetting self in Method Definitions
# โ Wrong way - forgot self parameter!
class BrokenClass:
def set_name(name): # ๐ซ Missing self!
self.name = name # ๐ฅ NameError: name 'self' is not defined
# โ
Correct way - always include self!
class WorkingClass:
def set_name(self, name): # โ
self is first parameter
self.name = name # ๐ฏ Now it works!
๐คฏ Pitfall 2: Using Class Variables Instead of Instance Variables
# โ Dangerous - shared between all instances!
class BadShoppingCart:
items = [] # ๐ฅ Class variable - shared by ALL carts!
def add_item(self, item):
self.items.append(item) # ๐ฑ Modifies the class variable!
# Creating multiple carts
cart1 = BadShoppingCart()
cart2 = BadShoppingCart()
cart1.add_item("๐ Apple")
print(cart2.items) # ['๐ Apple'] - Wait, what?! ๐ฑ
# โ
Safe - each instance has its own items!
class GoodShoppingCart:
def __init__(self):
self.items = [] # โ
Instance variable - unique to each cart!
def add_item(self, item):
self.items.append(item) # โ
Modifies only this cart's items
# Now it works correctly
cart1 = GoodShoppingCart()
cart2 = GoodShoppingCart()
cart1.add_item("๐ Apple")
print(cart2.items) # [] - Empty, as expected! โ
๐คฆ Pitfall 3: Forgetting to Return self for Method Chaining
# โ Breaks method chaining
class Calculator:
def __init__(self):
self.value = 0
def add(self, n):
self.value += n
# ๐ฅ Forgot to return self!
calc = Calculator()
# calc.add(5).add(3) # ๐ฅ AttributeError: 'NoneType' has no attribute 'add'
# โ
Enable method chaining by returning self
class BetterCalculator:
def __init__(self):
self.value = 0
def add(self, n):
self.value += n
return self # โ
Return self for chaining!
def multiply(self, n):
self.value *= n
return self # โ
Consistent pattern
calc = BetterCalculator()
result = calc.add(5).multiply(3).add(10) # โ
Works beautifully!
print(calc.value) # 25
๐ ๏ธ Best Practices
- ๐ฏ Always Use self: Make it the first parameter in instance methods
- ๐ Initialize in init: Set all instance variables in the constructor
- ๐ก๏ธ Keep Instance Data Private: Use self to encapsulate object state
- ๐จ Consistent Naming: Always call it
self
, notthis
orme
- โจ Method Chaining: Return
self
from methods that modify state
๐งช Hands-On Exercise
๐ฏ Challenge: Build a Virtual Pet System
Create a virtual pet that uses self
to manage its state:
๐ Requirements:
- โ Pet has name, species, hunger, happiness, and energy levels
- ๐ Feeding reduces hunger and increases happiness
- ๐ฎ Playing increases happiness but uses energy
- ๐ด Sleeping restores energy
- ๐ Status display shows all stats with emoji indicators
- ๐จ Different pet species have different needs!
๐ Bonus Points:
- Add pet aging over time
- Implement pet tricks that can be learned
- Create pet mood based on stats
๐ก Solution
๐ Click to see solution
# ๐ฏ Virtual Pet System with self management!
import random
class VirtualPet:
def __init__(self, name, species):
# ๐จ Initialize pet attributes
self.name = name # ๐ Pet's name
self.species = species # ๐พ Type of pet
self.age = 0 # ๐
Age in days
self.hunger = 50 # ๐ 0-100 (0 = full)
self.happiness = 50 # ๐ 0-100 (100 = very happy)
self.energy = 50 # โก 0-100 (100 = full energy)
self.tricks = [] # ๐ช Learned tricks
self.is_sleeping = False # ๐ด Sleep status
# ๐ฏ Species-specific traits
self._set_species_traits()
def _set_species_traits(self):
# ๐พ Different pets have different needs
if self.species == "Dog":
self.emoji = "๐"
self.energy_drain = 3 # Dogs are energetic!
self.hunger_rate = 2 # Moderate appetite
elif self.species == "Cat":
self.emoji = "๐ฑ"
self.energy_drain = 1 # Cats are lazy
self.hunger_rate = 1 # Light eaters
elif self.species == "Hamster":
self.emoji = "๐น"
self.energy_drain = 4 # Very active!
self.hunger_rate = 3 # Always hungry
else:
self.emoji = "๐พ"
self.energy_drain = 2
self.hunger_rate = 2
def feed(self, food_type="regular"):
# ๐ Feed the pet
if self.is_sleeping:
return f"{self.name} is sleeping! ๐ด"
food_values = {
"regular": {"hunger": -20, "happiness": 5},
"treat": {"hunger": -10, "happiness": 15},
"gourmet": {"hunger": -30, "happiness": 20}
}
values = food_values.get(food_type, food_values["regular"])
self.hunger = max(0, self.hunger + values["hunger"])
self.happiness = min(100, self.happiness + values["happiness"])
return f"{self.emoji} {self.name} enjoyed the {food_type} food! Yum! ๐"
def play(self, activity="fetch"):
# ๐ฎ Play with pet
if self.is_sleeping:
return f"{self.name} is sleeping! ๐ด"
if self.energy < 20:
return f"{self.emoji} {self.name} is too tired to play! ๐ช"
activities = {
"fetch": {"energy": -15, "happiness": 20},
"puzzle": {"energy": -10, "happiness": 15},
"cuddle": {"energy": -5, "happiness": 10}
}
values = activities.get(activity, activities["fetch"])
self.energy = max(0, self.energy + values["energy"])
self.happiness = min(100, self.happiness + values["happiness"])
self.hunger += 5 # Playing makes them hungry!
# Chance to learn a trick!
if random.random() > 0.7 and activity == "puzzle":
self._learn_trick()
return f"{self.emoji} {self.name} loved playing {activity}! ๐"
def sleep(self, hours=8):
# ๐ด Rest to restore energy
if self.is_sleeping:
return f"{self.name} is already sleeping! ๐ค"
self.is_sleeping = True
energy_gained = hours * 10
self.energy = min(100, self.energy + energy_gained)
self.hunger += hours * 2 # Get hungry while sleeping
# Age the pet
self.age += hours / 24
self.is_sleeping = False
return f"{self.emoji} {self.name} woke up refreshed after {hours} hours! ๐"
def _learn_trick(self):
# ๐ช Learn a new trick
tricks_pool = ["Sit", "Roll Over", "High Five", "Dance", "Speak", "Play Dead"]
available_tricks = [t for t in tricks_pool if t not in self.tricks]
if available_tricks:
new_trick = random.choice(available_tricks)
self.tricks.append(new_trick)
self.happiness = min(100, self.happiness + 10)
print(f"๐ {self.name} learned a new trick: {new_trick}!")
def perform_trick(self):
# ๐ญ Show off a trick
if not self.tricks:
return f"{self.emoji} {self.name} doesn't know any tricks yet! ๐คท"
if self.energy < 10:
return f"{self.emoji} {self.name} is too tired to perform! ๐ช"
trick = random.choice(self.tricks)
self.energy -= 10
self.happiness += 5
return f"{self.emoji} {self.name} performs: {trick}! ๐"
def get_mood(self):
# ๐ Determine mood based on stats
avg_stat = (self.happiness + self.energy + (100 - self.hunger)) / 3
if avg_stat >= 80:
return "ecstatic ๐คฉ"
elif avg_stat >= 60:
return "happy ๐"
elif avg_stat >= 40:
return "content ๐"
elif avg_stat >= 20:
return "grumpy ๐"
else:
return "miserable ๐ข"
def status(self):
# ๐ Display pet status
print(f"\n{'='*40}")
print(f"{self.emoji} {self.name} the {self.species} (Age: {self.age:.1f} days)")
print(f"{'='*40}")
print(f"๐ Happiness: {'โค๏ธ' * (self.happiness // 20)}{'๐ค' * (5 - self.happiness // 20)} {self.happiness}%")
print(f"โก Energy: {'๐' * (self.energy // 20)}{'๐ชซ' * (5 - self.energy // 20)} {self.energy}%")
print(f"๐ Hunger: {'๐' * (self.hunger // 20)}{'๐ฆด' * (5 - self.hunger // 20)} {self.hunger}%")
print(f"๐ญ Mood: {self.get_mood()}")
if self.tricks:
print(f"๐ช Tricks: {', '.join(self.tricks)}")
print(f"{'='*40}\n")
def time_passes(self):
# โฐ Simulate time passing
if not self.is_sleeping:
self.hunger = min(100, self.hunger + self.hunger_rate)
self.energy = max(0, self.energy - self.energy_drain)
self.happiness = max(0, self.happiness - 1)
if self.hunger > 80:
self.happiness = max(0, self.happiness - 5)
print(f"โ ๏ธ {self.name} is very hungry!")
if self.energy < 20:
self.happiness = max(0, self.happiness - 3)
print(f"โ ๏ธ {self.name} is exhausted!")
# ๐ฎ Let's play with our virtual pet!
# Create a pet
pet = VirtualPet("Buddy", "Dog")
# Daily routine
print("๐
Morning with Buddy!")
pet.status()
print(pet.feed("regular"))
print(pet.play("fetch"))
pet.time_passes()
print("\n๐ Afternoon activities!")
print(pet.play("puzzle"))
print(pet.feed("treat"))
print(pet.perform_trick())
pet.time_passes()
print("\n๐ Evening time!")
print(pet.sleep(8))
pet.status()
# Try with different species
cat = VirtualPet("Whiskers", "Cat")
cat.feed("gourmet")
cat.play("cuddle")
cat.sleep(12) # Cats love to sleep!
cat.status()
๐ Key Takeaways
Youโve learned so much! Hereโs what you can now do:
- โ Understand self as the instance reference ๐ช
- โ Use self to manage instance attributes and methods ๐ก๏ธ
- โ Avoid common self pitfalls that trip up beginners ๐ฏ
- โ Implement method chaining using self ๐
- โ Build complex classes with proper state management! ๐
Remember: self
is your objectโs best friend - it keeps everything organized and lets each instance be unique! ๐ค
๐ค Next Steps
Congratulations! ๐ Youโve mastered the self
parameter!
Hereโs what to do next:
- ๐ป Practice with the virtual pet exercise above
- ๐๏ธ Build your own class-based project using
self
properly - ๐ Move on to our next tutorial: Class Methods and Static Methods
- ๐ Share your creative class implementations with others!
Remember: Every Python expert started by understanding self
. Keep coding, keep learning, and most importantly, have fun! ๐
Happy coding! ๐๐โจ