নিচে চারটি ধাপে সাজানো ২৪টি হাতে-কলমে প্রজেক্ট আছে। প্রতিটি প্রজেক্টে একটি ছোট ব্রিফ আর উদাহরণ দেওয়া আছে — নিজে বানানোর চেষ্টা করুন, তারপর নিজের অ্যাপ্রোচ মিলিয়ে দেখতে সমাধান দেখুন-এ ক্লিক করুন। এখানে ব্রাউজারে রান করার সুবিধা নেই — নিজের এডিটরে (VS Code, IDLE, বা এরকম কিছু) লিখে রান করুন, ঠিক যেমন যেকোনো বাস্তব Python প্রোগ্রাম করবেন।
প্রোগ্রামটি ১ থেকে ১০০-এর মধ্যে একটি গোপন নম্বর বেছে নেয়। প্লেয়ার সঠিক উত্তর না পাওয়া পর্যন্ত গেস করতে থাকে, আর প্রোগ্রাম প্রতিটি গেস অনেক বেশি নাকি অনেক কম বলে দেয়।
Guess the number: 50
Too high!
Guess the number: 25
Too low!
Guess the number: 37
Correct! You got it in 3 tries.
কনসেপ্ট
যেভাবে বানানো হলো
random.randint(1, 100) দিয়ে — এটা ১ থেকে ১০০-এর মধ্যে (দুই প্রান্ত সহ) একটি র্যান্ডম পূর্ণসংখ্যা রিটার্ন করে।while True-এর ভেতরে রাখুন, যাতে প্লেয়ার না জেতা পর্যন্ত প্রোগ্রাম জিজ্ঞেস করতেই থাকে — এটা নিজে থেকে থামে না, শুধু লুপের ভেতরের break-ই থামায়।if / elif / else দিয়ে তুলনা করা হয়: অনেক কম, অনেক বেশি, নাকি সঠিক।attempts += 1 লুপের প্রতিটা পাকে চলে, তাই break চলার সময় ততক্ষণে এটা গেস গোনা হয়ে গেছে।ট্রেস: number = 63। গেস 30 → too low। গেস 80 → too high। গেস 63 → correct, attempts হয় 3, লুপ থেমে যায়।
সম্পূর্ণ কোড
import random
number = random.randint(1, 100)
attempts = 0
while True:
guess = int(input("Guess the number: "))
attempts += 1
if guess < number:
print("Too low!")
elif guess > number:
print("Too high!")
else:
print(f"Correct! You got it in {attempts} tries.")
break
লুপটি `break` না চলা পর্যন্ত জিজ্ঞেস করতেই থাকে — বাকি সবকিছু শুধু ঠিক করে কখন সেটা হওয়া উচিত।
ব্যবহারকারীর কাছ থেকে দুটি সংখ্যা আর একটি operator (+, -, *, /) নিন, তারপর ফলাফল প্রিন্ট করুন। শূন্য দিয়ে ভাগ করলে যেন প্রোগ্রাম ক্র্যাশ না করে সেটা সামলান।
Enter first number: 25
Enter operator (+, -, *, /): -
Enter second number: 8
Result: 17.0
কনসেপ্ট
যেভাবে বানানো হলো
float(input(...)) দিয়ে নিন যাতে দশমিক সংখ্যাও কাজ করে, শুধু পূর্ণসংখ্যা না — int() "17.5" নিতে রাজি হবে না।== দিয়ে তুলনা করা হয়, কখনো সংখ্যায় কনভার্ট করা হয় না — এটা "+", "-", "*", "/" এই ক্যারেক্টারগুলোর একটাই থেকে যায়।if / elif / else operator একবার চেক করে ঠিক একটা branch চালায় — একটা মিলে গেলে Python বাকি elif আর চেক করে না।if আছে যা ভাগ করার আগে num2 == 0 কিনা চেক করে — নাহলে ZeroDivisionError দিয়ে ক্র্যাশ করত।ট্রেস: num1 = 20, operator = "*", num2 = 5 → + বাদ, - বাদ, *-এ মিলে যায়, প্রিন্ট হয় 100।
সম্পূর্ণ কোড
num1 = float(input("Enter first number: "))
operator = input("Enter operator (+, -, *, /): ")
num2 = float(input("Enter second number: "))
if operator == "+":
print("Result:", num1 + num2)
elif operator == "-":
print("Result:", num1 - num2)
elif operator == "*":
print("Result:", num1 * num2)
elif operator == "/":
if num2 != 0:
print("Result:", num1 / num2)
else:
print("Cannot divide by zero!")
else:
print("Invalid operator!")
প্রতিটি branch ঠিক একটা কাজ করে — এক-branch-এক-কাজের এই অভ্যাসটা পরে অনেক বড় প্রোগ্রামেও কাজে লাগে।
প্রোগ্রাম চলাকালীন list-এ task যোগ করা, দেখা, আর মুছে ফেলার জন্য একটি মেনু-চালিত কনসোল অ্যাপ।
1. Add Task
2. View Tasks
3. Remove Task
4. Exit
Enter your choice: 2
Your Tasks:
1. Study Python
2. Go for a walk
কনসেপ্ট
যেভাবে বানানো হলো
tasks শুরু হয় একটা খালি list হিসেবে — .append() শেষে যোগ করে, .pop(index) পজিশন অনুযায়ী বাদ দেয়।while True-এর ভেতরে থাকে, তাই ব্যবহারকারী Exit বেছে break না চালানো পর্যন্ত এটা বারবার দেখাতে থাকে।enumerate(tasks, start=1) পজিশন আর আইটেম দুটোই একসাথে দেয়, তাই ব্যবহারকারীকে দেখানো নম্বরের জন্য আলাদা কাউন্টার লাগে না।n - 1 ব্যবহার হয় কারণ ব্যবহারকারী 1 থেকে গোনা নম্বর দেখে, কিন্তু Python-এর list 0 থেকে শুরু হয় — স্ক্রিনে "2" নম্বর task আসলে list-এ index 1।ট্রেস: "Study Python" তারপর "Exercise" যোগ করলে tasks = ["Study Python", "Exercise"]; task 1 মুছলে থাকে ["Exercise"]।
সম্পূর্ণ কোড
tasks = []
while True:
print("\n1. Add Task\n2. View Tasks\n3. Remove Task\n4. Exit")
choice = input("Enter your choice: ")
if choice == "1":
tasks.append(input("Enter task: "))
print("Task added!")
elif choice == "2":
if not tasks:
print("No tasks.")
else:
for i, task in enumerate(tasks, start=1):
print(i, ".", task)
elif choice == "3":
n = int(input("Enter task number to remove: "))
if 1 <= n <= len(tasks):
tasks.pop(n - 1)
print("Task removed!")
else:
print("Invalid task number.")
elif choice == "4":
print("Goodbye!")
break
else:
print("Invalid choice!")
`enumerate(tasks, start=1)` পজিশন আর আইটেম দুটোই একসাথে দেয়, তাই ব্যবহারকারীকে দেখানো নম্বরের জন্য আলাদা কাউন্টার লাগে না।
কয়েকটি বিষয়ের নম্বর জিজ্ঞেস করুন, তারপর total, average, আর letter grade হিসেব করে প্রিন্ট করুন।
Enter marks: 85
Enter marks: 72
Enter marks: 90
Total: 247
Average: 82.33
Grade: B
কনসেপ্ট
যেভাবে বানানো হলো
for লুপ আর .append() দিয়ে নির্দিষ্ট সংখ্যক নম্বর সংগ্রহ করুন, একটা একটা করে list বানিয়ে।sum(marks) এক কলেই list-এর সব আইটেম যোগ করে দেয় — আলাদা accumulator লুপ লাগে না।len(marks) দিয়ে ভাগ করলে total থেকে average হয়ে যায়, যা যতগুলো নম্বর দেওয়া হয়েছে তার সাথে নিজে থেকেই মানিয়ে নেয়।elif চেইনটা সবচেয়ে বড় গ্রেড থেকে শুরু করে লেখা, কারণ Python প্রথম true condition-এ থেমে যায় — >= 90-এর আগে >= 60 চেক করলে পাশ করা প্রতিটা ছাত্রই D পেত।ট্রেস: marks = [85, 72, 90] → total 247, average 82.33 → 90 চেক (না), 80 চেক (হ্যাঁ) → গ্রেড B।
সম্পূর্ণ কোড
marks = []
for i in range(3):
marks.append(float(input("Enter marks: ")))
total = sum(marks)
average = total / len(marks)
if average >= 90:
grade = "A"
elif average >= 80:
grade = "B"
elif average >= 70:
grade = "C"
elif average >= 60:
grade = "D"
else:
grade = "F"
print("\nTotal:", total)
print("Average:", round(average, 2))
print("Grade:", grade)
`elif` চেইন উপর থেকে নিচে চেক হয় আর প্রথম true condition-এ থেমে যায় — তাই এটা সবচেয়ে বড় গ্রেড থেকে শুরু করে সাজানো।
ব্যবহারকারীকে একটার পর একটা item আর price যোগ করতে দিন যতক্ষণ না 'done' টাইপ করে, তারপর কার্ট আর মোট দেখান।
Enter item name (or 'done' to finish): Apple
Enter price: 50
...
Apple - 50
Milk - 60
Total: 110
কনসেপ্ট
যেভাবে বানানো হলো
items আর prices — দুটো list একসাথে তৈরি হয় — একটাতে append() করলেই সাথে সাথে অন্যটাতেও একই কাজ হয়, তাই items[i] আর prices[i] সবসময় একই প্রোডাক্টের কথা বলে।while True, আর টাইপ করা "done"-ই বের হওয়ার শর্ত, নির্দিষ্ট কোনো সংখ্যা না — যখন আগে থেকে জানা নেই কতগুলো এন্ট্রি হবে তখন এটা কাজে লাগে।range(len(items))) কারণ একসাথে দুটো list-এর একই পজিশনে পৌঁছানোর জন্য একটা শেয়ার্ড index দরকার — শুধু for item in items দিয়ে একই সাথে prices-এও পৌঁছানো যেত না।ট্রেস: Apple 50, Milk 60, Bread 40 টাইপ করে, তারপর "done" → লুপ শেষ হওয়ার পর total 150 প্রিন্ট হয়।
সম্পূর্ণ কোড
items = []
prices = []
while True:
item = input("Enter item name (or 'done' to finish): ")
if item == "done":
break
prices.append(float(input("Enter price: ")))
items.append(item)
print("\nShopping Cart")
total = 0
for i in range(len(items)):
print(items[i], "-", prices[i])
total += prices[i]
print("Total:", total)
`items` আর `prices` দুটো আলাদা list, যেগুলো পজিশন অনুযায়ী সিঙ্কে থাকে — `items[i]` আর `prices[i]` সবসময় একই প্রোডাক্টের কথা বলে।
একটি পাসওয়ার্ড কমপক্ষে ৮ ক্যারেক্টার কিনা, আর তাতে একটি সংখ্যা, একটি বড় হাতের আর একটি ছোট হাতের অক্ষর আছে কিনা চেক করুন।
Enter your password: Hello123
Strong password!
কনসেপ্ট
যেভাবে বানানো হলো
any(c.isdigit() for c in password) প্রতিটা ক্যারেক্টার চেক করে আর শর্ত মেলা প্রথম ক্যারেক্টার পেলেই থেমে যায় — "অন্তত একটা ক্যারেক্টার মিলেছে কিনা" জিজ্ঞেস করার একটা সংক্ষিপ্ত উপায়।True/False দেয়।elif চেইন শুধু প্রথম যে সমস্যা পায় সেটাই জানায় — length সবার আগে, কারণ ক্যারেক্টার যাই থাকুক, খুব ছোট পাসওয়ার্ড এমনিতেই ফেল করে।ট্রেস: "hello123" → length 8 ঠিক আছে, সংখ্যা আছে, বড় হাতের অক্ষর নেই → uppercase চেকে থেমে যায়, প্রিন্ট হয় "add an uppercase letter."
সম্পূর্ণ কোড
password = input("Enter your password: ")
has_number = any(c.isdigit() for c in password)
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
if len(password) < 8:
print("Weak password - must have at least 8 characters.")
elif not has_number:
print("Weak password - add a number.")
elif not has_upper:
print("Weak password - add an uppercase letter.")
elif not has_lower:
print("Weak password - add a lowercase letter.")
else:
print("Strong password!")
`any(c.isdigit() for c in password)` আসলে একই flag-while-looping আইডিয়া যা `for` লুপে `has_number = True` লিখে করা যেত — শুধু ছোট করে লেখা।
৫ রাউন্ড কম্পিউটারের বিপক্ষে rock-paper-scissors খেলুন আর শেষে স্কোর প্রিন্ট করুন।
Round 1
Choose rock, paper, or scissors: rock
Computer chose: scissors
You win!
...
Final Score
You: 3
Computer: 2
কনসেপ্ট
যেভাবে বানানো হলো
random.choice(choices)-ই কম্পিউটারের চাল অনিশ্চিত করে তোলে — প্রতি রাউন্ডে list থেকে একটা আইটেম র্যান্ডমলি বেছে নেয়।or দিয়ে একটা elif-এ জোড়া — প্রতিটা bracket-করা জোড়াকে একটা বাক্য হিসেবে পড়ুন: "rock scissors-কে হারায়।"player in choices এমন সবকিছু ধরে যা draw-ও না, win-ও না, কিন্তু আসল একটা choice — শেষের else শুধু "banana"-র মতো সত্যিকারের ভুল ইনপুট ধরার জন্য থাকে।for i in range(5)-এর ভেতরে চালালে পুরো রাউন্ড পাঁচবার হয়, আর player_score ও computer_score প্রতিবার লুপ পার হয়েও থেকে যায় কারণ এগুলো লুপের বাইরে ডিফাইন করা।ট্রেস: কম্পিউটার বেছে নেয় "paper", প্লেয়ার টাইপ করে "rock" → draw না, player-win কম্বিনেশনও না, কিন্তু "rock" choices-এ আছে → কম্পিউটার জেতে।
সম্পূর্ণ কোড
import random
choices = ["rock", "paper", "scissors"]
player_score = 0
computer_score = 0
for i in range(5):
print("\nRound", i + 1)
player = input("Choose rock, paper, or scissors: ")
computer = random.choice(choices)
print("Computer chose:", computer)
if player == computer:
print("Draw!")
elif (player == "rock" and computer == "scissors") or \
(player == "paper" and computer == "rock") or \
(player == "scissors" and computer == "paper"):
print("You win!")
player_score += 1
elif player in choices:
print("Computer wins!")
computer_score += 1
else:
print("Invalid choice!")
print("\nFinal Score")
print("You:", player_score)
print("Computer:", computer_score)
তিনটা জেতার কম্বিনেশন আসলে গেমের নিয়ম মাত্র, `or` দিয়ে জোড়া — প্রতিটা লাইনকে একটা বাক্য হিসেবে পড়ুন: 'rock scissors-কে হারায়'।
একের পর এক প্রশ্ন করুন, প্রতিটা উত্তর চেক করুন, আর শেষে স্কোর প্রিন্ট করুন।
Question 1
What is the capital of India?
Your answer: Delhi
Correct!
...
Your score: 3 / 4
কনসেপ্ট
যেভাবে বানানো হলো
questions আর answers — দুটো list index অনুযায়ী একসাথে চলে — Shopping Cart-এর items/prices-এর মতোই সম্পর্ক।for q in questions-এর বদলে for i in range(len(questions)) ব্যবহার হয় কারণ লুপের একই সময়ে দুটো list-এই পৌঁছাতে একই i দরকার।.lower() মানে "Delhi", "delhi", আর "DELHI" — সবগুলোই সঠিক গণ্য হবে; capitalization আর ঠিক-ভুলের পার্থক্য তৈরি করবে না।ট্রেস: i = 2, questions[2] হলো "What is 5 + 5?", ব্যবহারকারী টাইপ করে "10", answers[2] হলো "10" → মিলে যায়, score বাড়ে।
সম্পূর্ণ কোড
questions = [
"What is the capital of India?",
"How many days are in a week?",
"What is 5 + 5?",
"Which language are we learning?",
]
answers = ["delhi", "7", "10", "python"]
score = 0
for i in range(len(questions)):
print("\nQuestion", i + 1)
print(questions[i])
user_answer = input("Your answer: ")
if user_answer.lower() == answers[i]:
print("Correct!")
score += 1
else:
print("Wrong! Correct answer:", answers[i])
print("\nYour score:", score, "/", len(questions))
ব্যবহারকারীর উত্তরে `.lower()` মানে 'Delhi', 'delhi', আর 'DELHI' — সবগুলোই গণ্য হবে; এটা না থাকলে শুধু capitalization-এর জন্যই একটা সঠিক উত্তর ভুল ধরা হতো।
নাম/ফোন জোড়া হিসেবে সেভ করা contact যোগ, দেখা, আর সার্চ করার জন্য একটি মেনু-চালিত অ্যাপ।
1. Add Contact
2. View Contacts
3. Search Contact
4. Exit
Enter choice: 3
Enter name to search: Rahul
Name: Rahul
Phone: 9876543210
কনসেপ্ট
যেভাবে বানানো হলো
[name, phone] — বড় contacts list-এর ভেতরে থাকা একটা list, এজন্যই contact[0] আর contact[1] এভাবে কাজ করে।found flag ব্যবহার হয়: শুরুতে False, মিল পেলেই True-তে বদলে যায়, তারপর লুপ শেষে একবার চেক করে "not found" প্রিন্ট করবে কিনা ঠিক হয়।.lower() থাকায় নাম যেভাবেই টাইপ করা হোক না কেন সার্চ মিলে যায়।ট্রেস: "Rahul" নামে সেভ করা contact-এর বিপরীতে "rahul" সার্চ করলে → দুই পাশই "rahul"-এ নেমে আসে → মিল পাওয়া যায়।
সম্পূর্ণ কোড
contacts = []
while True:
print("\n1. Add Contact\n2. View Contacts\n3. Search Contact\n4. Exit")
choice = input("Enter choice: ")
if choice == "1":
name = input("Enter name: ")
phone = input("Enter phone number: ")
contacts.append([name, phone])
print("Contact added!")
elif choice == "2":
if not contacts:
print("No contacts.")
else:
for contact in contacts:
print("Name:", contact[0], "| Phone:", contact[1])
elif choice == "3":
search = input("Enter name to search: ")
found = False
for contact in contacts:
if contact[0].lower() == search.lower():
print("Name:", contact[0])
print("Phone:", contact[1])
found = True
if not found:
print("Contact not found.")
elif choice == "4":
print("Goodbye!")
break
else:
print("Invalid choice!")
প্রতিটা contact একটা ছোট list `[name, phone]`, যেটা বড় `contacts` list-এর ভেতরে থাকে — এই list-এর-ভেতরে-list গঠনটাই Intermediate লেভেলে dictionary-র list হিসেবে আবার দেখবেন।
ক্যাটাগরি আর পরিমাণ অনুযায়ী খরচ রেকর্ড করার জন্য একটি মেনু-চালিত অ্যাপ, যা চলমান মোট দেখায়।
1. Add Expense
2. View Expenses
3. Show Total
4. Exit
Enter choice: 3
Total expenses: 800
কনসেপ্ট
যেভাবে বানানো হলো
[category, amount] — বড় expenses list-এর ভেতরে একটা ছোট list।sum(expense[1] for expense in expenses) একটা generator expression: প্রতিটা expense-এ ঘুরে শুধু amount (index 1) বের করে এক লাইনেই সব যোগ করে দেয়। লুপ দিয়ে করলে হতো total = 0-এর পর for লুপের ভেতরে total += expense[1]।ট্রেস: expenses = [["Food", 200], ["Transport", 100]] → generator প্রথমে 200 তারপর 100 দেখে → total হয় 300।
সম্পূর্ণ কোড
expenses = []
while True:
print("\n1. Add Expense\n2. View Expenses\n3. Show Total\n4. Exit")
choice = input("Enter choice: ")
if choice == "1":
category = input("Enter category: ")
amount = float(input("Enter amount: "))
expenses.append([category, amount])
print("Expense added!")
elif choice == "2":
if not expenses:
print("No expenses recorded.")
else:
for expense in expenses:
print(expense[0], "-", expense[1])
elif choice == "3":
total = sum(expense[1] for expense in expenses)
print("Total expenses:", total)
elif choice == "4":
print("Goodbye!")
break
else:
print("Invalid choice!")
`sum(expense[1] for expense in expenses)` শুধু পরিমাণগুলো যোগ করে, ক্যাটাগরি বাদ দিয়ে — এটাই total-এর লুপের আইডিয়া, এক লাইনে লেখা।
function ব্যবহার করে একটি মেনু-চালিত ব্যাংক সিমুলেটর — balance দেখা, deposit, আর withdraw, প্রতিটা নিজের একটা function হিসেবে, যা আপডেট হওয়া balance রিটার্ন করে।
===== BANK =====
1. Check Balance
2. Deposit
3. Withdraw
4. Exit
Enter choice: 2
Enter amount: 500
Deposit successful!
কনসেপ্ট
যেভাবে বানানো হলো
show_balance, deposit, withdraw — তাই মেনুর কাজ ছোট হয়ে যায় "কোন function ডাকতে হবে সেটা ঠিক করা"-তে, নিজে কাজটা করায় না।deposit(balance) বর্তমান balance-কে parameter হিসেবে ভেতরে নেয়, নতুন balance বাইরে রিটার্ন করে — function-এর বাইরে থাকা balance নামের কোনো ভ্যারিয়েবল কখনো ছোঁয় না।balance = deposit(balance) মনে রাখার মতো প্যাটার্ন: বর্তমান মান ভেতরে পাঠান, যা ফেরত আসে সেটা ধরুন, একই নামে সেভ করুন।ট্রেস: balance = 1000, deposit() 500 চায়, 1500 রিটার্ন করে, মূল প্রোগ্রামে balance হয়ে যায় 1500।
সম্পূর্ণ কোড
def show_balance(balance):
print("Balance:", balance)
def deposit(balance):
amount = float(input("Enter amount to deposit: "))
print("Deposit successful!")
return balance + amount
def withdraw(balance):
amount = float(input("Enter amount to withdraw: "))
if amount <= balance:
print("Withdrawal successful!")
return balance - amount
print("Insufficient balance!")
return balance
balance = 1000
while True:
print("\n===== BANK =====\n1. Check Balance\n2. Deposit\n3. Withdraw\n4. Exit")
choice = input("Enter choice: ")
if choice == "1":
show_balance(balance)
elif choice == "2":
balance = deposit(balance)
elif choice == "3":
balance = withdraw(balance)
elif choice == "4":
print("Thank you!")
break
else:
print("Invalid choice!")
`balance = deposit(balance)` মূল প্যাটার্ন: বর্তমান মান ভেতরে পাঠান, নতুন মান ফেরত পান, সেভ করুন — কোনো `global` লাগে না।
প্রতিটা task-এ completed স্ট্যাটাস যোগ করে To-Do List-কে আরও বড় করুন, add/view/complete/delete-এর জন্য function ব্যবহার করে।
1 ○ Learn Python
2 ✓ Exercise
Mark task 1 as done
1 ✓ Learn Python
2 ✓ Exercise
কনসেপ্ট
যেভাবে বানানো হলো
[text, False] — একটা ছোট list, যার index 1 একটা Boolean যা বলে কাজটা শেষ হয়েছে কিনা, ঠিক Expense Tracker-এর [category, amount]-এর মতোই দুটো তথ্য একসাথে রাখার আইডিয়া।tasks.append(...) আর tasks.pop(...) ভেতরে পাঠানো list-টাকে সরাসরি বদলে দেয় — এই function গুলোর tasks রিটার্ন করার দরকার নেই, deposit()/withdraw()-এর মতো না, যাদের নতুন balance রিটার্ন করতেই হতো কারণ সংখ্যা সরাসরি বদলানো যায় না।tasks[index][1] = True দুই ধাপ গভীরে পৌঁছায়: প্রথমে সেই পজিশনের task-এ, তারপর তার দ্বিতীয় উপাদানে।ট্রেস: tasks[0] হলো ["Learn Python", False] → tasks[0][1] = True-এর পর হয় ["Learn Python", True]।
সম্পূর্ণ কোড
def add_task(tasks):
tasks.append([input("Enter task: "), False])
print("Task added!")
def view_tasks(tasks):
if not tasks:
print("No tasks.")
return
for i, task in enumerate(tasks, start=1):
status = "✓" if task[1] else "○"
print(i, status, task[0])
def complete_task(tasks):
view_tasks(tasks)
n = int(input("Enter task number: "))
if 1 <= n <= len(tasks):
tasks[n - 1][1] = True
print("Task completed!")
def delete_task(tasks):
view_tasks(tasks)
n = int(input("Enter task number to delete: "))
if 1 <= n <= len(tasks):
tasks.pop(n - 1)
print("Task deleted!")
tasks = []
while True:
print("\n1. Add 2. View 3. Complete 4. Delete 5. Exit")
choice = input("Enter choice: ")
if choice == "1": add_task(tasks)
elif choice == "2": view_tasks(tasks)
elif choice == "3": complete_task(tasks)
elif choice == "4": delete_task(tasks)
elif choice == "5": break
else: print("Invalid choice!")
`tasks.append(...)` আর `tasks.pop(...)` list-টাকে সরাসরি বদলে দেয়, তাই এই function গুলোর `return` করার দরকার নেই — শুধু নম্বর বা স্ট্রিং-এর মতো মান বের করে আনতে `return` লাগে।
Expense Tracker-কে নতুন করে বানান যাতে খরচ dictionary হিসেবে সেভ হয় আর একটি JSON ফাইলে সেভ থাকে, রান শেষ হওয়ার পরও টিকে থাকে।
expenses.json:
[{"category": "Food", "amount": 200}]
Total expenses: 200
কনসেপ্ট
যেভাবে বানানো হলো
{"category": ..., "amount": ...} — expense["amount"] বলে দেয় মানে কী; expense[1] বলত না।json.dump(expenses, file) পুরো Python list-of-dictionaries-কে JSON টেক্সটে বদলে ডিস্কে লিখে দেয়; প্রোগ্রাম আবার চালু হলে json.load(file) উল্টো কাজটা করে।try/except FileNotFoundError থাকায় একদম প্রথম রান — যখন ফাইলটা এখনো নেই — ক্র্যাশ না করে একটা খালি list দিয়ে শুরু করে।ট্রেস: প্রথম রান, ফাইল নেই → FileNotFoundError ধরা পড়ে → expenses = []। একটা expense যোগ করে সেভ করার পর, পরের রানে json.load() সেটা ঠিকঠাক আবার তৈরি করে।
সম্পূর্ণ কোড
import json
def load_expenses():
try:
with open("expenses.json", "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_expenses(expenses):
with open("expenses.json", "w") as file:
json.dump(expenses, file, indent=4)
def add_expense(expenses):
expense = {
"category": input("Enter category: "),
"amount": float(input("Enter amount: ")),
}
expenses.append(expense)
save_expenses(expenses)
print("Expense added!")
def show_total(expenses):
total = sum(e["amount"] for e in expenses)
print("Total expenses:", total)
expenses = load_expenses()
while True:
print("\n1. Add 2. View 3. Total 4. Exit")
choice = input("Enter choice: ")
if choice == "1": add_expense(expenses)
elif choice == "2":
for e in expenses: print(e["category"], "-", e["amount"])
elif choice == "3": show_total(expenses)
elif choice == "4": break
else: print("Invalid choice!")
`expense[1]`-এর বদলে `expense['amount']` — এটাই list থেকে dictionary-তে যাওয়ার আসল কারণ: key নিজেই বলে দেয় মানটা কী বোঝায়।
কুইজের প্রশ্ন হার্ডকোড না করে আলাদা একটি questions.json ফাইল থেকে লোড করুন, তারপর কুইজ চালান।
questions.json:
[{"question": "5 + 3?", "options": [...], "answer": "8"}]
Score: 2 / 3
কনসেপ্ট
যেভাবে বানানো হলো
question, options, answer — আর পুরো কুইজ এগুলোর একটা list, যা সরাসরি Python ফাইলে না লিখে questions.json থেকে লোড হয়।quiz.py শুধু জানে কীভাবে কুইজ চালাতে হয়, কী কী প্রশ্ন আছে সেটা না।ask_question() True বা False রিটার্ন করে — sum(ask_question(q) for q in questions) কাজ করে কারণ Python যোগ করার সময় True-কে 1 আর False-কে 0 হিসেবে গোনে।ট্রেস: q["options"] হলো ["6", "7", "8", "9"], ব্যবহারকারী টাইপ করে "3" → index 2 → q["options"][2] হলো "8", যা q["answer"]-এর সাথে মেলে → True রিটার্ন করে।
সম্পূর্ণ কোড
import json
def load_questions():
try:
with open("questions.json", "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def ask_question(q):
print("\n" + q["question"])
for i, option in enumerate(q["options"], start=1):
print(i, ".", option)
choice = int(input("Enter your answer: "))
if q["options"][choice - 1] == q["answer"]:
print("Correct!")
return True
print("Wrong! Correct answer:", q["answer"])
return False
questions = load_questions()
score = sum(ask_question(q) for q in questions)
print(f"\nScore: {score} / {len(questions)}")
`sum(ask_question(q) for q in questions)` কাজ করে কারণ Python-এ `True` মানে `1` আর `False` মানে `0` — প্রতিটা সঠিক উত্তর মোটের সাথে এক যোগ করে।
Contact Book-কে dictionary-র list দিয়ে নতুন করে বানান, search, update, আর delete সহ, JSON-এ সেভ করে।
Update Rahul
Enter new phone: 9999999999
Contact updated!
কনসেপ্ট
যেভাবে বানানো হলো
contact[1]-এর বদলে contact["phone"]।c["phone"] = new_phone) — delete-এর মতো সরিয়ে আবার যোগ করার দরকার নেই।.pop() একটা index নেয় — এজন্যই সাধারণ for c in contacts-এর বদলে enumerate() দিয়ে লুপ হয়।save_contacts() ডাকা হয় — মেমরিতে list বদলালেই ডিস্কের ফাইল বদলায় না, যতক্ষণ না এই কলটা হয়।ট্রেস: Rahul-এর ফোন নম্বর update করলে মিলে যাওয়া dictionary-টা খুঁজে পাওয়া যায়, সরাসরি তার c["phone"] সেট হয়, তারপর সেভ হয় — list-এ dictionary-র identity একই থাকে, শুধু তার ভেতরের একটা মান বদলায়।
সম্পূর্ণ কোড
import json
def load_contacts():
try:
with open("contacts.json", "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_contacts(contacts):
with open("contacts.json", "w") as file:
json.dump(contacts, file, indent=4)
def add_contact(contacts):
contacts.append({
"name": input("Enter name: "),
"phone": input("Enter phone: "),
})
save_contacts(contacts)
def update_contact(contacts):
name = input("Enter name to update: ")
for c in contacts:
if c["name"].lower() == name.lower():
c["phone"] = input("Enter new phone: ")
save_contacts(contacts)
print("Contact updated!")
return
print("Contact not found.")
def delete_contact(contacts):
name = input("Enter name to delete: ")
for i, c in enumerate(contacts):
if c["name"].lower() == name.lower():
contacts.pop(i)
save_contacts(contacts)
print("Contact deleted!")
return
print("Contact not found.")
contacts = load_contacts()
# ... menu loop connecting add_contact / update_contact / delete_contact,
# the same shape as the Expense Tracker's menu above.
Update করা মানে শুধু list-এর ভেতরে থাকা dictionary-র `c["phone"]` বদলানো — delete-এর মতো সরিয়ে আবার যোগ করার দরকার নেই।
ব্যবহারকারীর বেছে নেওয়া দৈর্ঘ্যের একটি র্যান্ডম পাসওয়ার্ড বানান, যাতে অক্ষর, সংখ্যা, আর symbol থাকবে।
Enter password length: 12
Generated password: aT9#kLp2!qXz
কনসেপ্ট
যেভাবে বানানো হলো
string.ascii_letters আর string.digits হলো Python-এর standard library-র রেডি-মেড ক্যারেক্টার সেট — হাতে না লিখেই পুরো অক্ষরমালা আর সংখ্যা পাওয়া যায়।random.choice(characters) সেই একসাথে করা সেট থেকে একটা র্যান্ডম ক্যারেক্টার বেছে নেয়; একটা generator expression দিয়ে প্রতিটা পজিশনের জন্য একবার করে চালিয়ে, "".join(...)-এর ভেতরে পুরো পাসওয়ার্ড এক লাইনেই তৈরি হয়ে যায়।ট্রেস: length 4 → চারটা আলাদা random.choice() কল → ফলাফল জোড়া লেগে একটা স্ট্রিং হয়ে যায়, যেমন "aT9#"।
সম্পূর্ণ কোড
import random
import string
length = int(input("Enter password length: "))
characters = string.ascii_letters + string.digits + "!@#$%^&*"
password = "".join(random.choice(characters) for _ in range(length))
print("Generated password:", password)
`string.ascii_letters` আর `string.digits` Python-এর standard library-র রেডি-মেড ক্যারেক্টার সেট — হাতে করে পুরো অক্ষরমালা লেখার দরকার নেই।
একটি ATM-স্টাইল মেনু, যেখানে balance, deposit, বা withdraw করার আগে PIN চেক করা হয় — ৩ বার ভুল PIN দিলে লক হয়ে যায়।
Enter PIN: 0000
Wrong PIN. 2 attempts left.
Enter PIN: 1234
Welcome!
কনসেপ্ট
যেভাবে বানানো হলো
check_pin() সর্বোচ্চ ৩ বার লুপ চালায়, সঠিক PIN দেওয়া মাত্রই True রিটার্ন করে — একটা তাড়াতাড়ি return সাথে সাথেই function থেকে বের করে দেয়, লুপের বাকিটা আর চলে না।return False-এ।if not check_pin():-এর ভেতরেই চলে — একটা function-এর রিটার্ন ভ্যালু ঠিক করে দিচ্ছে এরপর কী হবে, শুধু function নিজে কী করছে তা না।ট্রেস: দুইবার ভুল PIN, তৃতীয়বারে সঠিক → check_pin() তৃতীয় চেষ্টাতেই True রিটার্ন করে, fail branch-এ কখনো পৌঁছায় না।
সম্পূর্ণ কোড
CORRECT_PIN = "1234"
balance = 1000
def check_pin():
for attempt in range(3):
pin = input("Enter PIN: ")
if pin == CORRECT_PIN:
return True
print(f"Wrong PIN. {2 - attempt} attempts left.")
return False
if not check_pin():
print("Too many wrong attempts. Card blocked.")
else:
print("Welcome!")
while True:
print("\n1. Balance 2. Deposit 3. Withdraw 4. Exit")
choice = input("Enter choice: ")
if choice == "1":
print("Balance:", balance)
elif choice == "2":
balance += float(input("Enter amount: "))
elif choice == "3":
amount = float(input("Enter amount: "))
if amount <= balance:
balance -= amount
else:
print("Insufficient balance!")
elif choice == "4":
break
else:
print("Invalid choice!")
`check_pin()` `True` বা `False` রিটার্ন করে, আর বাকি প্রোগ্রাম শুধু `if not check_pin():`-এর ভেতরেই চলে — একটা function-এর রিটার্ন ভ্যালু ঠিক করে দিচ্ছে এরপর কী হবে।
বই available নাকি borrowed তা ট্র্যাক করুন, বই যোগ, borrow, return, আর available বই লিস্ট করার function সহ।
1. Add Book 2. Borrow 3. Return 4. List Available 5. Exit
Enter choice: 2
Enter title to borrow: Python Basics
Borrowed!
কনসেপ্ট
যেভাবে বানানো হলো
{"title": ..., "borrowed": False} — Advanced To-Do App-এর completed স্ট্যাটাসের মতোই একটা dictionary-র ভেতরে boolean flag রাখার আইডিয়া।borrow_book() শুধু সেই বইয়ের সাথে মেলে যার borrowed এখনো False — আগে থেকে ধার নেওয়া বই আবার ধার করতে চাইলে "Not available"-এ গিয়ে পড়ে।[b["title"] for b in books if not b["borrowed"]] একটা list comprehension: একই ফিল্টারিং for লুপ, কয়েক লাইনের বদলে এক expression-এ লেখা।ট্রেস: দুটো বই, একটা আগে থেকেই ধার নেওয়া → list comprehension শুধু এখনো available যেটা সেটাই রাখে।
সম্পূর্ণ কোড
books = []
def add_book(title):
books.append({"title": title, "borrowed": False})
def borrow_book(title):
for book in books:
if book["title"] == title and not book["borrowed"]:
book["borrowed"] = True
print("Borrowed!")
return
print("Not available.")
def return_book(title):
for book in books:
if book["title"] == title and book["borrowed"]:
book["borrowed"] = False
print("Returned!")
return
print("That book wasn't borrowed.")
def list_available():
available = [b["title"] for b in books if not b["borrowed"]]
print("\n".join(available) if available else "No books available.")
`[b["title"] for b in books if not b["borrowed"]]` একটা list comprehension — একই ফিল্টারিং `for` লুপ, এক লাইনে লেখা।
প্রোডাক্টের স্টক লেভেল ট্র্যাক করুন, restock, sell (স্টক চেক সহ), আর low-stock রিপোর্টের ব্যবস্থা রাখুন।
1. Add Product 2. Restock 3. Sell 4. Low Stock Report 5. Exit
Enter choice: 3
Sold 5 units of Notebook.
কনসেপ্ট
যেভাবে বানানো হলো
inventory একটা dictionary, সরাসরি প্রোডাক্টের নাম key হিসেবে ব্যবহার করে — inventory["Pen"] মানে কলমের স্টক সংখ্যা, নামের আলাদা কোনো list লাগে না।inventory.get(name, 0) প্রোডাক্ট এখনো যোগ না হলে ক্র্যাশ না করে 0 রিটার্ন করে — এমন key-এর জন্য inventory[name]-এর চেয়ে নিরাপদ যা নাও থাকতে পারে।sell() চেক করে যথেষ্ট স্টক আছে কিনা — Bank Account Simulator-এর withdraw()-এর মতোই "আগে চেক করো, তারপর করো" প্যাটার্ন।ট্রেস: inventory = {"Pen": 3}, 5টা বিক্রি করতে চাইলে → 3 >= 5 মিথ্যা → নেগেটিভ কাউন্ট না হয়ে "Not enough stock" দেখায়।
সম্পূর্ণ কোড
inventory = {}
def add_product(name, qty):
inventory[name] = inventory.get(name, 0) + qty
def sell(name, qty):
if inventory.get(name, 0) >= qty:
inventory[name] -= qty
print(f"Sold {qty} units of {name}.")
else:
print("Not enough stock.")
def low_stock_report(threshold=5):
for name, qty in inventory.items():
if qty < threshold:
print(name, "-", qty, "left")
`inventory.get(name, 0)` প্রোডাক্ট এখনও যোগ না হলে ক্র্যাশ না করে `0` রিটার্ন করে — dictionary-র এমন key পড়ার নিরাপদ উপায় যা নাও থাকতে পারে।
এই লেভেলের সবকিছু একটা প্রোগ্রামে একসাথে করুন: স্টক সহ প্রোডাক্ট (dictionary), শপিং কার্ট, চেকআউট যা স্টক কমায়, আর একটি JSON-এ সেভ করা sales log।
1. Browse 2. Add to Cart 3. Checkout 4. Exit
Checkout total: ₹450
Sale recorded.
কনসেপ্ট
যেভাবে বানানো হলো
checkout() কার্টের প্রতিটা item-এর দাম products dictionary থেকে পড়ে, সব যোগ করে একটা total বানায়, আর একটা রেকর্ড — {"items": ..., "total": ...} — বাড়তে থাকা sales history-তে যোগ করে, যা প্রতিটা বিক্রির পর JSON-এ সেভ হয়।ট্রেস: কার্ট ["Pen", "Notebook"], products = {"Pen": 10, "Notebook": 40} সহ → total 50, একটা sale রেকর্ড যোগ হয়ে সেভ হয়।
সম্পূর্ণ কোড
import json
def load_sales():
try:
with open("sales.json", "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_sales(sales):
with open("sales.json", "w") as file:
json.dump(sales, file, indent=4)
products = {"Pen": 10, "Notebook": 40, "Eraser": 5}
cart = []
sales = load_sales()
def checkout(cart):
total = sum(products[item] for item in cart)
sales.append({"items": cart, "total": total})
save_sales(sales)
print("Checkout total:", total)
print("Sale recorded.")
এটা ইচ্ছাকৃতভাবে একটা কম্বিনেশন, নতুন কোনো আইডিয়া না — প্রোডাক্টের জন্য dictionary, কার্টের জন্য list, আর Expense Tracker-এর একই load/save JSON প্যাটার্ন, সব একসাথে একটা প্রোগ্রামে।
Level 1-এর Simple Calculator, Tkinter দিয়ে বাটন আর টেক্সট বক্স সহ নতুন করে বানানো, input()/print()-এর বদলে।
[ Entry: 25+8 ]
[ = ]
Result: 33
কনসেপ্ট
যেভাবে বানানো হলো
tk.Tk() লাগে — root window — আর একদম শেষে একবার root.mainloop() ডাকতে হয়, যা উইন্ডোটাকে খোলা রাখে আর ক্লিকের জন্য অপেক্ষা করায়, সাথে সাথে বন্ধ না করে।Entry আর Button-এর মতো widget আগে তৈরি হয়, তারপর .pack() দিয়ে জায়গামতো বসানো হয় — widget বানানো আর জায়গায় বসানো দুটো আলাদা ধাপ।command=calculate মানে: ক্লিক করলে এই function ডাকো — হাতে করে কোনো event-listener জোড়া লাগানোর দরকার নেই, Tkinter command argument দিয়ে এটা করে দেয়।ট্রেস: entry-তে 25+8 টাইপ করে =-এ ক্লিক করলে calculate() ডাকা হয়, যা টেক্সটটা হিসেব করে 33 দেখায়।
সম্পূর্ণ কোড
import tkinter as tk
def calculate():
try:
result_var.set(str(eval(entry.get())))
except Exception:
result_var.set("Error")
root = tk.Tk()
root.title("Calculator")
entry = tk.Entry(root, font=("Arial", 18))
entry.pack(fill="x", padx=10, pady=10)
result_var = tk.StringVar()
tk.Label(root, textvariable=result_var, font=("Arial", 14)).pack()
tk.Button(root, text="=", command=calculate).pack(pady=5)
root.mainloop()
`root.mainloop()` GUI প্রোগ্রামটাকে চালু আর ক্লিকের জন্য অপেক্ষারত রাখে — এটা না থাকলে উইন্ডোটা এক ঝলক দেখিয়েই বন্ধ হয়ে যেত, ঠিক যেমন `while True` মেনু ছাড়া একটা কনসোল প্রোগ্রাম এক পাক ঘুরেই শেষ হয়ে যায়।
একটি উইন্ডো যা ব্যবহারকারী টাইপ করার সাথে সাথে Celsius আর Fahrenheit-এর মধ্যে তাপমাত্রা কনভার্ট করে, আলাদা কোনো 'convert' বাটনে ক্লিক ছাড়াই।
Celsius: [ 100 ] → Fahrenheit: [ 212.0 ]
কনসেপ্ট
যেভাবে বানানো হলো
celsius.trace_add("write", convert) Celsius ফিল্ডের টেক্সট বদলালেই স্বয়ংক্রিয়ভাবে convert() চালায় — এটাই "event-driven" মানে: কিছু ঘটলে তার প্রতিক্রিয়ায় চলা কোড, উপর থেকে নিচে একবার চলার বদলে।fahrenheit = celsius * 9 / 5 + 32 — এখানে নতুন কিছু নেই; নতুন যেটা তা হলো এটা কখন চলে।ট্রেস: Celsius-এ "100" টাইপ করলে প্রতিটা কী-প্রেসে convert() চলে, আর পুরো সংখ্যা টাইপ হয়ে গেলে Fahrenheit দেখায় 212.0।
সম্পূর্ণ কোড
import tkinter as tk
def convert(*args):
try:
c = float(celsius.get())
fahrenheit_var.set(f"{c * 9 / 5 + 32:.1f}")
except ValueError:
fahrenheit_var.set("")
root = tk.Tk()
root.title("Temperature Converter")
celsius = tk.StringVar()
celsius.trace_add("write", convert)
fahrenheit_var = tk.StringVar()
tk.Label(root, text="Celsius").grid(row=0, column=0)
tk.Entry(root, textvariable=celsius).grid(row=0, column=1)
tk.Label(root, text="Fahrenheit").grid(row=1, column=0)
tk.Label(root, textvariable=fahrenheit_var).grid(row=1, column=1)
root.mainloop()
`celsius.trace_add("write", convert)` টেক্সট বদলালেই স্বয়ংক্রিয়ভাবে `convert()` চালায় — এটাই "event-driven" মানে: কিছু ঘটলে তার প্রতিক্রিয়ায় চলা কোড, উপর থেকে নিচে একবার চলার বদলে।
একটি ছোট বিলিং উইন্ডো: item আর quantity বেছে নিন, উইন্ডোতে দেখানো একটা বিল লিস্টে যোগ করুন, আর চলমান মোট দেখান।
Item: [Notebook v] Qty: [3] [Add]
Notebook x3 - ₹120
Total: ₹120
কনসেপ্ট
যেভাবে বানানো হলো
global total এখানে দরকার কারণ add_item() কোনো function-এর বাইরে তৈরি হওয়া একটা ভ্যারিয়েবল বদলাচ্ছে — Bank Account Simulator-এ প্রথম দেখা একই নিয়ম, শুধু এবার একটা মেনু function-এর বদলে বাটনের callback-এর ভেতরে।bill_list.insert("end", ...) একটা Listbox widget-এ এক লাইন যোগ করে, পুরো উইন্ডো আবার আঁকা ছাড়াই একটা দেখা-যাওয়া চলমান রেকর্ড তৈরি করে।ট্রেস: "Notebook" আর quantity 3 বেছে Add-এ ক্লিক করলে 40 * 3 = 120 হিসেব হয়, লিস্টে "Notebook x3 - ₹120" যোগ হয়, আর total লেবেল হয়ে যায় ₹120।
সম্পূর্ণ কোড
import tkinter as tk
PRICES = {"Notebook": 40, "Pen": 10, "Eraser": 5}
total = 0
def add_item():
global total
item = item_var.get()
qty = int(qty_entry.get())
cost = PRICES[item] * qty
total += cost
bill_list.insert("end", f"{item} x{qty} - ₹{cost}")
total_var.set(f"Total: ₹{total}")
root = tk.Tk()
root.title("Billing")
item_var = tk.StringVar(value="Notebook")
tk.OptionMenu(root, item_var, *PRICES.keys()).pack()
qty_entry = tk.Entry(root)
qty_entry.pack()
tk.Button(root, text="Add", command=add_item).pack()
bill_list = tk.Listbox(root)
bill_list.pack(fill="both", expand=True)
total_var = tk.StringVar(value="Total: ₹0")
tk.Label(root, textvariable=total_var).pack()
root.mainloop()
`global total` এখানে দরকার কারণ `add_item()` কোনো function-এর বাইরে তৈরি হওয়া একটা ভ্যারিয়েবল বদলাচ্ছে — একই নিয়ম যা Bank Account Simulator-এ প্রথম দেখেছিলেন, শুধু এবার একটা মেনু function-এর বদলে GUI callback-এর ভেতরে।
Bank Account Simulator-কে class হিসেবে নতুন করে বানান — account আর তার আচরণ (deposit, withdraw, balance) একসাথে একটা object-এ থাকে, আলাদা balance ভ্যারিয়েবল আর function-এর বদলে।
acc = BankAccount("Rahul", 1000)
acc.deposit(500)
acc.show_balance()
Rahul's balance: 1500
কনসেপ্ট
যেভাবে বানানো হলো
class BankAccount ডেটা (owner, balance) আর আচরণ (deposit, withdraw, show_balance) একসাথে একটা definition-এ বেঁধে ফেলে — account object তৈরি করার একটা ব্লুপ্রিন্ট।BankAccount(...) ডাকা হলে __init__ একবার, স্বয়ংক্রিয়ভাবে চলে — এখানেই self.owner আর self.balance শুরুর মান পায়।self দিয়েই বোঝা যায় — withdraw()-এর ভেতরে self.balance মানে "এই account-এর balance," class-এর বাইরে ভাসমান কোনো balance না।acc.deposit(500)-কে Level 2-এর balance = deposit(balance)-এর সাথে তুলনা করুন — account এখন নিজের ডেটা নিজের সাথেই বহন করে, তাই balance ভেতরে পাঠিয়ে নতুন একটা ফেরত নেওয়ার দরকার নেই; method সরাসরি self.balance আপডেট করে দেয়।ট্রেস: acc = BankAccount("Rahul", 1000), acc.deposit(500) সেই নির্দিষ্ট object-এ self.balance 1500 করে দেয়, তাই acc.show_balance() প্রিন্ট করে "Rahul's balance: 1500"।
সম্পূর্ণ কোড
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
print("Deposit successful!")
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
print("Withdrawal successful!")
else:
print("Insufficient balance!")
def show_balance(self):
print(f"{self.owner}'s balance: {self.balance}")
acc = BankAccount("Rahul", 1000)
acc.deposit(500)
acc.withdraw(200)
acc.show_balance()
Level 2-এর function-ভিত্তিক ভার্সনের সাথে তুলনা করুন: `self.balance` প্রতিটা function-এ `balance` ভেতরে-বাইরে পাঠানোর জায়গা নিয়ে নেয় — account এখন নিজের ডেটা নিজের সাথেই বহন করে। এটাই class-এর মূল আইডিয়া।
সমাধান না দেখে এগুলো সহজ মনে হলে, এরপর কোথায় যাবেন পাঠে virtual environment, pip, আর প্রথমে কোন framework বা library দেখা উচিত তা নিয়ে আলোচনা আছে।