অধ্যায় 06

লেখা নিয়ে কাজ — ইনডেক্স, স্লাইস আর f-string

লেখার ভেতর থেকে অংশ বের করা, পরিষ্কার করা, বদলানো, আর f-string দিয়ে পড়তে সহজ বার্তা তৈরি করা — সাথে লেখার অপরিবর্তনীয়তার নিয়ম।

35 মিনিটPython 3.12
  1. 1সমস্যা
  2. 2বোঝা
  3. 3উদাহরণ
  4. 4অনুমান
  5. 5নিজে করা
  6. 6কঠিন করা

যে সমস্যাটা আমরা সমাধান করছি

একটা ফর্ম থেকে নাম এসেছে: " Rafi Ahmed "। শুরুতে-শেষে বাড়তি স্পেস, আর আপনার দরকার শুধু প্রথম নামটা, আর একটা বার্তা — "Welcome, Rafi!"।

এই কাজটা — লেখা পরিষ্কার করা, তার ভেতর থেকে অংশ বের করা, আর সেটা দিয়ে নতুন বার্তা বানানো — প্রোগ্রামিংয়ের সবচেয়ে ঘন ঘন করা কাজগুলোর একটা। ব্যবহারকারীর নাম, ইমেইল, আইডি, ফাইলের নাম, ঠিকানা, API থেকে আসা উত্তর — সবই লেখা।

আর একটা জিনিস আজ পরিষ্কার হবে, যেটা না জানলে ঘণ্টা নষ্ট হয়: পাইথনে লেখা বদলানো যায় না। name.upper() লিখলে name বড় হাতের হয়ে যায় না। কেন হয় না আর তাহলে কী করতে হয়, সেটাই এই মিশনের সবচেয়ে দামি অংশ।

এই মিশন শেষে আপনি পারবেন

  • লেখার যেকোনো অক্ষর ইনডেক্স দিয়ে বের করতে, সামনে থেকে আর পেছন থেকে
  • স্লাইস দিয়ে একটা অংশ কেটে নিতে
  • strip, upper, lower, replace, split দিয়ে লেখা পরিষ্কার ও বদলাতে
  • বুঝতে কেন মেথডের ফলাফল ধরে রাখতে হয়
  • f-string দিয়ে পড়তে সহজ বার্তা তৈরি করতে

আগে যা জানা লাগবে: ভেরিয়েবল আর টাইপ।


কোটেশন — এক না দুই

পাইথনের কাছে 'Rafi' আর "Rafi" একই জিনিস। দুটো ধরন রাখা আছে যাতে লেখার ভেতরে কোটেশন থাকলে সমস্যা না হয়:

python
print("It's working")
print('She said "yes"')
text
It's working
She said "yes"

তিনটি কোটেশন দিলে একাধিক লাইনের লেখা রাখা যায়:

python
note = """Dear customer,
Your order is confirmed.
Thank you."""
print(note)
text
Dear customer,
Your order is confirmed.
Thank you.

আর \n লিখলে নতুন লাইন তৈরি হয়, \t দিলে ট্যাব:

python
print("Name:\tRafi\nRole:\tLearner")
text
Name:	Rafi
Role:	Learner

দৈর্ঘ্য আর ইনডেক্স

python
word = "PYTHON"

print(len(word))
print(word[0])
print(word[1])
print(word[-1])
print(word[-2])
text
6
P
Y
N
O

দুটো জিনিস মাথায় গাঁথতে হবে:

গোনা শুরু হয় শূন্য থেকে। প্রথম অক্ষরের ইনডেক্স 0, দ্বিতীয়টির 1। তাই ছয় অক্ষরের শব্দে শেষ অক্ষরের ইনডেক্স 5, 6 নয়। word[6] লিখলে IndexError আসবে। এই "এক কম" ভুলটা এত সাধারণ যে ইংরেজিতে এর আলাদা নাম আছে — off-by-one error।

ঋণাত্মক ইনডেক্স পেছন থেকে গোনে। word[-1] শেষ অক্ষর, word[-2] তার আগেরটা। শব্দটা কত লম্বা তা না জেনেই শেষ অক্ষর পাওয়ার এটাই সহজ উপায়।

স্লাইস — একটা অংশ কেটে নেওয়া

python
word = "PROGRAMMING"

print(word[0:7])
print(word[7:11])
print(word[:7])
print(word[7:])
print(word[-4:])
text
PROGRAM
MING
PROGRAM
MING
MING

word[a:b] মানে a থেকে শুরু করে b-এর আগে পর্যন্ত। শেষের সংখ্যাটি বাদ যায়।

শুরুতে এটা অস্বস্তিকর লাগে, কিন্তু এর একটা সুবিধা আছে: word[0:7] আর word[7:11] — দুটো টুকরো ঠিক জোড়া লেগে যায়, কোনো অক্ষর দুবার আসে না, কোনোটা বাদও পড়ে না। শুরুর দিকের সংখ্যা বাদ দিলে "একেবারে গোড়া থেকে", আর শেষের সংখ্যা বাদ দিলে "একেবারে শেষ পর্যন্ত" বোঝায়।

লেখা বদলানো যায় না

এটাই এই মিশনের সবচেয়ে জরুরি নিয়ম:

python
name = "rafi"
name[0] = "R"
text
TypeError: 'str' object does not support item assignment

একটা তৈরি হয়ে যাওয়া লেখার ভেতরের অক্ষর পাল্টানো যায় না। তাহলে বড় হাতের করা, স্পেস কাটা — এসব কীভাবে হয়? উত্তর: পাইথন পুরনোটা বদলায় না, একটা নতুন লেখা বানিয়ে ফেরত দেয়।

python
name = "  rafi  "

print(name.strip())
print(name.strip().upper())
print("After all that, name is still:", name)
text
rafi
RAFI
After all that, name is still:   rafi

name একটুও বদলায়নি। strip() একটা নতুন পরিষ্কার লেখা তৈরি করে দিয়েছে, আর আমরা সেটা শুধু ছেপে দিয়েছি — কোথাও রাখিনি।

তাই ফলাফলটা ধরে রাখতে হয়:

python
name = "  rafi  "
clean_name = name.strip().upper()
print(clean_name)
text
RAFI

অথবা একই নামে আবার বসিয়ে দিন — name = name.strip()। এই একটা ভুল, অর্থাৎ মেথড ডেকে ফলাফল না রাখা, শুরুর দিকে সবার হয়। আর ত্রুটি আসে না, তাই ধরা পড়তেও সময় লাগে।

কাজের মেথডগুলো

python
raw = "  Rafi Ahmed  "

print(raw.strip())
print(raw.strip().lower())
print(raw.strip().upper())
print(raw.strip().replace(" ", "_"))
print(len(raw), len(raw.strip()))
print("rafi" in raw.lower())
text
Rafi Ahmed
rafi ahmed
RAFI AHMED
Rafi_Ahmed
14 10
True
  • strip() — শুরু আর শেষের ফাঁকা জায়গা কাটে (মাঝেরগুলো নয়)
  • lower() / upper() — ছোট বা বড় হাতের অক্ষরে বদলায়
  • replace(a, b) — সব a-এর জায়গায় b বসায়
  • in — একটা লেখা আরেকটার ভেতরে আছে কি না বলে

আর split() লেখাকে টুকরো করে:

python
full_name = "Rafi Ahmed Khan"
parts = full_name.split(" ")

print(parts)
print(parts[0])
print(len(parts))
text
['Rafi', 'Ahmed', 'Khan']
Rafi
3

ওই বর্গাকার বন্ধনীর জিনিসটাকে বলে লিস্ট — সেটা নিয়ে আলাদা মিশন আছে। এখন শুধু জানুন, split() টুকরোগুলো এভাবে ফেরত দেয়, আর ইনডেক্স দিয়ে টুকরো বের করা যায়।

তুলনা করার আগে পরিষ্কার করে নিন। ব্যবহারকারী "Rafi " লিখলে সেটা "rafi"-এর সমান নয় — একটা বাড়তি স্পেস আর বড় হাতের অক্ষর মিলিয়ে তিনটে পার্থক্য। তাই তুলনার আগে .strip().lower() চালিয়ে নেওয়া প্রায় সব প্রজেক্টের নিয়ম।

f-string — বার্তা বানানোর সহজ উপায়

লেখার সাথে সংখ্যা মেশানো এখন পর্যন্ত ঝামেলার ছিল। f-string সেটা সহজ করে দেয় — কোটেশনের আগে একটা f, আর ভেতরে দ্বিতীয় বন্ধনীর মধ্যে যা খুশি:

python
name = "Rafi"
items = 3
price = 12.5

print(f"Hello, {name}!")
print(f"{items} items cost {items * price}")
print(f"Rounded: {items * price:.2f}")
text
Hello, Rafi!
3 items cost 37.5
Rounded: 37.50

তিনটি সুবিধা লক্ষ্য করুন: ভেতরে সরাসরি হিসাব করা যায় (items * price), টাইপ নিয়ে ভাবতে হয় না (সংখ্যা নিজে থেকেই লেখায় বদলে যায়), আর :.2f দিয়ে দশমিকের ঘর ঠিক করে দেওয়া যায় — অর্থের অঙ্ক দেখানোর সময় যেটা প্রতিবারই লাগে।

f ভুলে গেলে কী হয়, একবার দেখে রাখুন:

python
name = "Rafi"
print("Hello, {name}")
text
Hello, {name}

কোনো ত্রুটি নেই, শুধু বার্তাটা ভুল। এটা চোখে দেখা থাকলে পরে ধরতে সুবিধা হবে।


একটা সম্পূর্ণ উদাহরণ

account.py:

python
# Turn a raw form entry into a clean display name and a login id
raw_input_name = "   Rafi Ahmed   "
domain = "example.com"

clean = raw_input_name.strip()
parts = clean.split(" ")
first_name = parts[0]
last_name = parts[-1]

login_id = f"{first_name.lower()}.{last_name.lower()}"
email = f"{login_id}@{domain}"
initials = f"{first_name[0]}{last_name[0]}"

print(f"Display name : {clean}")
print(f"Login id     : {login_id}")
print(f"Email        : {email}")
print(f"Initials     : {initials}")
print(f"Name length  : {len(clean)} characters")
text
Display name : Rafi Ahmed
Login id     : rafi.ahmed
Email        : rafi.ahmed@example.com
Initials     : RA
Name length  : 10 characters

parts[-1] কেন? কারণ কারও নামে তিনটি অংশ থাকতে পারে। শেষ অংশটা পেছন থেকে ধরলে দুই অংশ আর তিন অংশ — দুই ক্ষেত্রেই কাজ করে।


কিছু ভাঙা অবস্থা ও তার সমাধান

IndexError: string index out of range যে ইনডেক্স চেয়েছেন সেটা লেখার দৈর্ঘ্যের বাইরে। মনে রাখুন, len(word) যদি ৬ হয়, বৈধ ইনডেক্স 0 থেকে 5। শেষ অক্ষর চাইলে word[-1] সবচেয়ে নিরাপদ।

TypeError: 'str' object does not support item assignment লেখার ভেতরের একটা অক্ষর বদলাতে চেয়েছেন। সেটা সম্ভব নয় — নতুন লেখা বানাতে হবে, যেমন word = "R" + word[1:]।

মেথড চালালাম, কিন্তু কিছুই বদলায়নি ফলাফলটা কোথাও রাখা হয়নি। name.strip() নিজে name বদলায় না; name = name.strip() লিখতে হবে।

strip() মাঝের স্পেস কাটছে না strip()-এর কাজ শুধু দুই প্রান্তে। মাঝেরগুলো সরাতে replace(" ", "") ব্যবহার করুন।

f-string-এ বার্তা ভুল আসছে কোটেশনের ঠিক আগে f আছে কি না দেখুন। f ছাড়া দ্বিতীয় বন্ধনী শুধু সাধারণ অক্ষর হিসেবে ছাপা হয়।

NameError — f-string-এর ভেতরের নামটি চেনা যাচ্ছে না দ্বিতীয় বন্ধনীর ভেতরে যে নামটা লিখেছেন, সেটা আগে তৈরি হয়নি বা বানানে ভুল আছে।