Follow Us
মাধ্যম নির্বাচন করুন / Select Medium:
Eng (English) Beng (বাংলা) Hindi (हिन्दी)
পশ্চিমবঙ্গ মধ্যশিক্ষা পর্ষদ (WBBSE) • শ্রেণি XII • Computer Science • অধ্যায় 1
আনুমানিক সময়: 120 Mins
অগ্রগতি: অধ্যয়নে সক্রিয়

Programming in Python (পাইথনে প্রোগ্রামিং)

পশ্চিমবঙ্গ উচ্চমাধ্যমিক শিক্ষা সংসদের (WBCHSE) দ্বাদশ শ্রেণির কম্পিউটার সায়েন্স পাঠ্যক্রমের প্রথম অধ্যায় 'পাইথনে প্রোগ্রামিং' (Programming in Python)-এর এই প্রামাণ্য ও পূর্ণাঙ্গ স্টাডি গাইডে স্বাগত। পাইথন হলো একটি আধুনিক, উচ্চস্তরের, ইন্টারপ্রেটেড, ডায়নামিকালি টাইপড এবং অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং ভাষা যা এর প্রাঞ্জল সিনট্যাক্স ও শক্তিশালী লাইব্রেরির জন্য বিশ্বজুড়ে সুপরিচিত। এই অধ্যায়ে শিক্ষার্থীরা একাদশ শ্রেণির প্রোগ্রামিং ধারণার ভিত্তির ওপর দাঁড়িয়ে পাইথনের অভ্যন্তরীণ আর্কিটেকচার গভীরভাবে অনুধাবন করবে। সোর্স কোড (.py) কীভাবে অ্যাবস্ট্রাক্ট সিনট্যাক্স ট্রি (AST) এবং মধ্যবর্তী বাইটকোডে (.pyc) রূপান্তরিত হয়ে পাইথন ভার্চুয়াল মেশিনে (PVM) নির্বাহ হয়, তা বিশদভাবে আলোচনা করা হয়েছে। এছাড়া পাইথনের মেমরি মডেল, অবজেক্ট রেফারেন্স, মিউটেবল বনাম ইমিউটেবল ডেটা টাইপের আচরণ, স্ট্রিং, লিস্ট ও টাপলের নিখুঁত স্লাইসিং ক্যালকুলাস, ডিকশনারি ও সেটের হ্যাশ-টেবিল মেকানিক্স, ফাংশনে আর্গুমেন্ট আদান-প্রদান (*args, **kwargs), LEGB স্কোপিং হায়ারার্কি, ফাইল I/O এবং ট্রাই-এক্সেপ্ট এক্সেপশন মডেলের পুঙ্খানুপুঙ্খ ব্যাখ্যা প্রদান করা হয়েছে যা উচ্চমাধ্যমিক পরীক্ষায় সর্বোচ্চ নম্বর অর্জনে সহায়ক।

অধ্যায়টির গুরুত্ব

আধুনিক সফটওয়্যার ইঞ্জিনিয়ারিং, ডেটা সায়েন্স, ক্লাউড কম্পিউটিং এবং কৃত্রিম বুদ্ধিমত্তা (AI) বিপ্লবের কেন্দ্রবিন্দুতে রয়েছে পাইথন। WBCHSE দ্বাদশ শ্রেণির শিক্ষার্থীদের জন্য পাইথন কেবল পাঠ্যবইয়ের একটি অধ্যায় নয়, বরং আধুনিক প্রযুক্তি জগতের সাথে সংযোগ স্থাপনের সবচেয়ে শক্তিশালী মাধ্যম। পাইথনের মেমরি রেফারেন্স ও গারবেজ কালেকশন পদ্ধতি বুঝতে পারলে মেমরি লিকের ঝুঁকি এড়িয়ে দক্ষ ও দ্রুতগতির কোড লেখা সম্ভব হয়। মিউটেবল (পরিবর্তনযোগ্য) ও ইমিউটেবল (অপরিবর্তনযোগ্য) ডেটা টাইপের সুনির্দিষ্ট পার্থক্য জানা থাকলে বহুধাপবিশিষ্ট সফটওয়্যারে অনাকাঙ্ক্ষিত পার্শ্বপ্রতিক্রিয়া প্রতিরোধ করা যায়। তদুপরি, ফাইল হ্যান্ডলিং ও সুরক্ষিত এক্সেপশন হ্যান্ডলিংয়ের দক্ষতা শিক্ষার্থীদের বাস্তবমুখী ডেটা প্রক্রিয়াকরণ ও মজবুত সফটওয়্যার তৈরিতে সাহায্য করে যা ইঞ্জিনিয়ারিং প্রবেশিকা ও পেশাগত ভবিষ্যতের পথ প্রশস্ত করে।

অধ্যায়ের বিষয়সূচি ও রূপরেখা

1 ১. পাইথনের সূচনা, স্থাপত্য ও সি-পাই...
2 ২. মেমরি মডেল, অবজেক্ট মিউটেবিলিটি...
3 ৩. শর্তাধীন শাখা নিয়ন্ত্রণ, লুপ পু...
4 ৪. সিকোয়েন্স ডেটা টাইপ: স্ট্রিং, ল...
5 ৫. হ্যাশ সংকলন: ডিকশনারি ও গাণিতিক...
6 ৬. মডুলার ফাংশন, LEGB স্কোপ, ফাইল I...

সম্পূর্ণ তত্ত্ব ও ধারণাগত আলোচনা

১. পাইথনের সূচনা, স্থাপত্য ও সি-পাইথন (CPython) এক্সিকিউশন পাইপলাইন

১.১ পাইথনের সূচনা, বৈশিষ্ট্য ও সি-পাইথন (CPython) এক্সিকিউশন পাইপলাইন

পাইথন প্রোগ্রামিং ভাষার প্রবক্তা হলেন ডাচ কম্পিউটার বিজ্ঞানী গুইডো ভ্যান রসাম (Guido van Rossum)। ১৯৮০-এর দশকের শেষের দিকে নেদারল্যান্ডসের Centrum Wiskunde & Informatica (CWI) গবেষণাগারে ABC ভাষার উত্তরসূরি হিসেবে তিনি পাইথনের বিকাশ শুরু করেন এবং ১৯৯১ সালের ফেব্রুয়ারিতে এর প্রথম সংস্করণ আনুষ্ঠানিকভাবে প্রকাশিত হয়। পাইথনের মূল দর্শন হলো প্রাঞ্জল কোড লিখন, স্পষ্ট সিনট্যাক্স এবং বহু-পদ্ধতিগত প্রোগ্রামিং সমর্থন (প্রসিডিউরাল, অবজেক্ট-ওরিয়েন্টেড ও ফাংশনাল)।

পাইথনের মৌলিক স্থাপত্যিক বৈশিষ্ট্যসমূহ:
  • হাইব্রিড অনুবাদ ব্যবস্থা (Hybrid Execution): পাইথন সম্পূর্ণ কম্পাইল্ড (যেমন C/C++) বা সরাসরি লাইন-বাই-লাইন ইন্টারপ্রেটেড ভাষা নয়। আদর্শ সি-পাইথন (CPython) প্রথমে সোর্স কোডকে একটি মধ্যবর্তী বাইটকোডে (.pyc) সংকলন করে এবং পরবর্তীতে ভার্চুয়াল মেশিনের মাধ্যমে কার্যকর করে।
  • ডায়নামিক টাইপিং (Dynamically Typed): কোডে চলকের ডেটা টাইপ আগে থেকে ঘোষণা করতে হয় না; রানটাইমে অবজেক্টের মানের ওপর ভিত্তি করে স্বয়ংক্রিয়ভাবে টাইপ নির্ধারিত হয়।
  • স্বয়ংক্রিয় মেমরি ব্যবস্থাপনা: রেফারেন্স কাউন্টিং (Reference Counting) এবং সাইক্লিক গারবেজ কালেক্টরের মাধ্যমে অব্যবহৃত মেমরি স্বয়ংক্রিয়ভাবে মুক্ত হয়।
  • ব্যাটারিজ ইনক্লুডেড (Batteries Included): গণিত, ফাইল সিস্টেম, নেটওয়ার্কিং, স্ট্রিং প্রসেসিং ইত্যাদির জন্য সমৃদ্ধ স্ট্যান্ডার্ড লাইব্রেরি বিল্ট-ইন থাকে।
১.২ সি-পাইথন নির্বাহ প্রক্রিয়ার ৪টি স্তর
ধাপ যন্ত্রাংশ / প্রক্রিয়া কার্যপ্রণালী ও আউটপুট
১. লেক্সিক্যাল অ্যানালিসিস টোকেনাইজার (Tokenizer) সোর্স কোডকে ক্ষুদ্র ক্ষুদ্র উপাদান বা টোকেনে বিভক্ত করে (কিওয়ার্ড, আইডেন্টিফায়ার, লিটারেল, অপারেটর ও ইনডেন্টেশন টোকেন INDENT/DEDENT)।
২. সিনট্যাক্স পার্সিং পার্সার (Parser) সিনট্যাক্স ব্যাকরণ যাচাই করে মেমরিতে অ্যাবস্ট্রাক্ট সিনট্যাক্স ট্রি (AST) গঠন করে। কোনো ব্যাকরণগত ভুল থাকলে এই পর্যায়েই SyntaxError ঘটে।
৩. বাইটকোড কম্পাইলেশন কোড জেনারেটর AST থেকে প্ল্যাটফর্ম-স্বাধীন ইন্টারমিডিয়েট বাইটকোড (.pyc) তৈরি হয় যা pycache ডিরেক্টরিতে ক্যাশ হিসেবে জমা থাকে।
৪. ভার্চুয়াল মেশিন রানটাইম পাইথন ভার্চুয়াল মেশিন (PVM) একটি স্ট্যাক-ভিত্তিক ইন্টারপ্রেটার ইঞ্জিন যা বাইটকোডের প্রতিটি নির্দেশ ধারাবাহিকভাবে পড়ে কম্পিউটারের প্রসেসরে কার্যকর করে।
১.৩ সিনট্যাকটিক ইনডেন্টেশন (Indentation) ও PEP 8 নীতিমালা

অন্যান্য ভাষার মতো পাইথনে কোড ব্লক বোঝাতে দ্বিতীয় বন্ধনী {} ব্যবহৃত হয় না। এর পরিবর্তে ইনডেন্টেশন বা শূন্যস্থান ব্যবহৃত হয়:

  • ইনডেন্টেশনের নিয়ম (PEP 8): প্রতি কোড ব্লকের জন্য আদর্শ হলো ঠিক ৪টি স্পেস (Spaces) ব্যবহার করা। ট্যাব ও স্পেসের মিশ্রণ সম্পূর্ণ নিষিদ্ধ (পাইথন ৩-এ এটি TabError ঘটায়)।
  • চলকের নামকরণের শর্ত (Identifiers): বর্ণমালা বা আন্ডারস্কোর (_) দিয়ে নাম শুরু হতে হবে, কোনো সংখ্যা দিয়ে শুরু হতে পারবে না। পাইথন কেস-সেনসিটিভ (যেমন Num ও num পৃথক)। সংরক্ষিত কিওয়ার্ড (যেমন def, class, if, while) চলক হিসেবে ব্যবহৃত হতে পারে না।
  • কমেন্ট ও ডকস্ট্রিং: এক লাইনের মন্তব্যের জন্য # ব্যবহৃত হয়। ফাংশন বা ক্লাসের ডকুমেন্টেশনের জন্য ট্রিপল কোট """...""" ডকস্ট্রিং হিসেবে ব্যবহৃত হয় যা .doc দিয়ে পড়া যায়।

২. মেমরি মডেল, অবজেক্ট মিউটেবিলিটি ও অপারেটর মেকানিক্স

২.১ পাইথনের মেমরি মডেল: রেফারেন্স পয়েন্টার হিসেবে চলক

C বা Java-র মতো পাইথনে চলক কোনো মেমরি বাক্স নয় যাতে সরাসরি মান জমা থাকে। পাইথনে সবকিছুই অবজেক্ট। একটি চলক কেবল হিপ মেমরিতে থাকা একটি অবজেক্টের দিকে নির্দেশ করা একটি রেফারেন্স পয়েন্টার বা নামফলক (Tag):

# মেমরি রেফারেন্স ও id() ফাংশনের উদাহরণ
x = 250
y = x
print(id(x) == id(y))  # True: একই মেমরি ঠিকানা নির্দেশ করছে
print(x is y)          # True: আইডেন্টিটি সমান

x = x + 1              # নতুন ইন্টিজার অবজেক্ট 251 তৈরি হলো
print(id(x) == id(y))  # False: x এখন নতুন মেমরি নির্দেশ করছে
print(y)               # 250: y পূর্বের অবজেক্টেই বহাল আছে
২.২ পরিবর্তনীয়তা বনাম অপরিবর্তনীয়তা (Mutable vs. Immutable)

পাইথনে প্রতিটি অবজেক্টের ৩টি বৈশিষ্ট্য থাকে: আইডেন্টিটি (id()), টাইপ (type()), এবং মান (Value)।

শ্রেণিবিভাগ ডেটা টাইপসমূহ মেমরি রূপান্তর আচরণ হ্যাশাবিলিটি ও ডিকশনারি কী
ইমিউটেবল (Immutable - অপরিবর্তনযোগ্য) int, float, complex, bool, str, tuple, frozenset তৈরির পর এর ভেতরের মান পরিবর্তন করা অসম্ভব। কোনো পরিবর্তন ঘটলে মেমরিতে সম্পূর্ণ নতুন অবজেক্ট তৈরি হয়। হ্যাশেবল (Hashable): ডিকশনারির কী বা সেটের উপাদান হিসেবে ব্যবহারযোগ্য।
মিউটেবল (Mutable - পরিবর্তনযোগ্য) list, dict, set মেমরির ঠিকানা অপরিবর্তিত রেখেই নিজস্ব স্থানে (in-place) উপাদান যোগ, বিয়োগ বা সংশোধন করা যায়। আন-হ্যাশেবল (Unhashable): ডিকশনারির কী বা সেটে ব্যবহার করলে TypeError দেখা দেয়।
২.৩ অপারেটরের শ্রেণিবিভাগ ও অগ্রাধিকারের নিয়মাবলী

পাইথনে অপারেটরসমূহের মূল বৈশিষ্ট্যসমূহ:

  • পাটিগাণিতিক অপারেটর: +, -, *, প্রকৃত ভাগ / (সর্বদা ফ্লোট তৈরি করে: 7 / 2 = 3.5), ফ্লোর ডিভিশন // (পূর্ণসংখ্যায় নিম্নমুখী ভাগ: 7 // 2 = 3, -7 // 2 = -4), ভাগশেষ %, এবং সূচকীকরণ (ডান দিক থেকে কাজ করে: 2 3 ** 2 = 512)।
  • সম্পর্কযুক্ত ও চেইন্ড কম্প্যারিজন: ==, !=, >, <, >=, <=। পাইথনে 10 < x <= 50 সরাসরি লেখা যায় যা (10 < x) and (x <= 50) এর সমতুল্য।
  • লজিক্যাল শর্ট-সার্কিট অপারেটর:
    • and: প্রথম মিথ্যা মান পেলে তৎক্ষণাৎ তা ফেরত দেয়, অন্যথায় শেষ সত্য মান দেয় (যেমন: 0 and 5 দেয় 0; 3 and 7 দেয় 7)।
    • or: প্রথম সত্য মান পেলেই তা ফেরত দেয় (যেমন: 5 or 10 দেয় 5)।
    • not: বুলিয়ান মান উল্টে দেয়।
  • আইডেন্টিটি (is, is not) বনাম সমতা (==, !=): == কেবল দুটি অবজেক্টের মান সমান কিনা তা যাচাই করে। পক্ষান্তরে is যাচাই করে দুটি চলক মেমরির একই অবজেক্ট নির্দেশ করছে কিনা (id(a) == id(b))।
  • সদস্যপদ অপারেটর (Membership): in এবং not in সিকোয়েন্সে কোনো উপাদান আছে কিনা তা $O(N)$ বা সেটে গড় $O(1)$ সময়ে যাচাই করে।

৩. শর্তাধীন শাখা নিয়ন্ত্রণ, লুপ পুনরাবৃত্তি ও লুপ-এলস লজিক

৩.১ শর্তাধীন শাখা নিয়ন্ত্রণ: if, elif ও else

পাইথনে শূন্য (0, 0.0), None, False এবং যেকোনো খালি সংগ্রহ ("", [], (), {}, set()) স্বতঃস্ফূর্তভাবে মিথ্যা (Falsey) হিসেবে গণ্য হয়। অন্য সকল মান সত্য (Truthy) বিবেচিত হয়।

# শর্তাধীন কাঠামো ও টার্নারি অপারেটর
marks = 82

if marks >= 90:
    grade = 'AA'
elif marks >= 80:
    grade = 'A+'
elif marks >= 70:
    grade = 'A'
else:
    grade = 'Pass'

# টার্নারি এক্সপ্রেশন (এক লাইনের if-else):
status = "Honors" if marks >= 80 else "General"
৩.২ পুনরাবৃত্তি কাঠামো: while ও for লুপ এবং range() এর কৌশল

পাইথনে পুনরাবৃত্তিমূলক কাজের জন্য দুটি লুপ ব্যবহৃত হয়:

  • while লুপ: যতক্ষণ একটি শর্ত সত্য থাকে ততক্ষণ লুপ চলে। ভেতরে মান পরিবর্তনের নির্দেশ না থাকলে ইনফিনিট লুপ তৈরি হয়।
  • for লুপ ও ইটারেটর: পাইথনের for লুপ মূলত একটি ইটারেটর যা সিকোয়েন্সের প্রতিটি উপাদান একে একে পড়ে।
  • range(start, stop, step) অবজেক্ট: এটি মেমরিতে সম্পূর্ণ তালিকা তৈরি না করে প্রয়োজনে সংখ্যা উৎপন্ন করে:
    • range(5): 0 থেকে 4 পর্যন্ত সংখ্যা দেয় (শেষ মান 5 বাদ)।
    • range(1, 10, 2): 1, 3, 5, 7, 9 উৎপন্ন করে।
    • range(10, 0, -2): ঋণাত্মক ধাপে 10, 8, 6, 4, 2 দেয়।
৩.৩ জাম্প স্টেটমেন্ট ও পাইথনের অনন্য লুপ-এলস (Loop-Else) গঠন

লুপ নিয়ন্ত্রণে তিনটি বিশেষ কিওয়ার্ড থাকে:

  • break: লুপকে তৎক্ষণাৎ বন্ধ করে দেয় এবং লুপের পরবর্তী লাইনে চলে যায়।
  • continue: বর্তমান পুনরাবৃত্তির বাকি অংশ বাদ দিয়ে পরবর্তী পুনরাবৃত্তিতে চলে যায়।
  • pass: ফাঁকা ব্লক তৈরি করার জন্য সিনট্যাক্টিক প্লেসহোল্ডার হিসেবে ব্যবহৃত হয়।
  • লুপের সাথে else ব্লক: লুপের সাথে যুক্ত else ব্লকটি কেবল তখনই কার্যকর হয় যদি লুপটি স্বাভাবিকভাবে সম্পূর্ণ হয় এবং কোনো break দ্বারা বিঘ্নিত না হয়:
# মৌলিক সংখ্যা নির্ণয়ে for-else এর প্রয়োগ
n = 37
for d in range(2, int(n ** 0.5) + 1):
    if n % d == 0:
        print(f"{n} যৌগিক সংখ্যা।")
        break
else:
    # break কার্যকর না হলে এটি চলবে
    print(f"{n} একটি মৌলিক সংখ্যা!")
কীওয়ার্ড / নির্দেশ মূল ভূমিকা ও আচরণ লুপ প্রবাহে প্রভাব লুপের else ব্লক কার্যকর হয়?
break শর্তাধীনভাবে লুপের সম্পূর্ণ কাজ বন্ধ করে। বর্তমান লুপটি তৎক্ষণাৎ সমাপ্ত করে নিয়ন্ত্রণ বাইরে নিয়ে যায়। না (else ব্লক বাতিল করে দেয়)
continue বর্তমান পুনরাবৃত্তির অবশিষ্ট অংশ এড়িয়ে যায়। বর্তমান চক্রের বাকি লাইন বাদ দিয়ে পরবর্তী পুনরাবৃত্তিতে চলে যায়। হ্যাঁ (লুপ স্বাভাবিকভাবে শেষ হলে)
pass সিনট্যাক্টিক ফাঁকা প্লেসহোল্ডার (No-op)। কোনো পরিবর্তন করে না; নিয়ন্ত্রণ স্বাভাবিকভাবে পরবর্তী লাইনে চলে যায়। হ্যাঁ (স্বাভাবিক সমাপ্তিতে কোনো বাধা দেয় না)

৪. সিকোয়েন্স ডেটা টাইপ: স্ট্রিং, লিস্ট ও টাপলের বিশদ বিশ্লেষণ

৪.১ সিকোয়েন্সের ইনডেক্সিং ও স্লাইসিং ক্যালকুলাস

স্ট্রিং, লিস্ট এবং টাপল একইরকম দ্বিমুখী ইনডেক্সিং সমর্থন করে:

  • ধনাত্মক ইনডেক্স: প্রথম উপাদান 0 থেকে শুরু করে শেষ উপাদান n - 1 পর্যন্ত।
  • ঋণাত্মক ইনডেক্স: শেষ উপাদান -1 থেকে শুরু করে প্রথম উপাদান -n পর্যন্ত।
  • স্লাইসিং সূত্র seq[start:stop:step]: start ইনডেক্স থেকে শুরু করে stop-এর ঠিক পূর্ব পর্যন্ত step ব্যবধানে উপ-অংশ নিষ্কাশন করে।
    • seq[::-1] লিখলে পুরো সিকোয়েন্স উল্টো দিক থেকে নতুন কপি হিসেবে তৈরি হয়।
    • স্লাইসিং সীমানা অতিক্রম করলেও কখনো IndexError দেয় না।
৪.২ স্ট্রিং (str): অপরিবর্তনশীলতা ও প্রধান মেথডসমূহ

স্ট্রিং হলো ইউনিকোড অক্ষরের অপরিবর্তনীয় ক্রম। প্রধান মেথডসমূহ:

  • .upper(), .lower(), .title(), .capitalize(): কেস পরিবর্তন।
  • .strip(), .lstrip(), .rstrip(): অপ্রয়োজনীয় ফাঁকা জায়গা বা অক্ষর ছাঁটাই।
  • .find(sub): সাবস্ট্রিং না পেলে -1 দেয়; .index(sub): সাবস্ট্রিং না পেলে ValueError দেয়।
  • .split(sep): স্ট্রিংকে ভেঙে লিস্ট বানায়; sep.join(list): লিস্টের শব্দগুলোকে জোড়া লাগিয়ে স্ট্রিং বানায়।
  • f-strings (পাইথন ৩.৬+): সহজ স্ট্রিং ফরম্যাটিং: f"নাম: {name}, রোল: {roll:03d}"।
৪.৩ লিস্ট (list): ডায়নামিক অ্যারে ও লিস্ট কম্প্রিহেনশন

লিস্ট হলো পরিবর্তনযোগ্য ক্রমিক ডেটা কাঠামো যা বিভিন্ন ধরনের ডেটা ধারণ করতে পারে।

অপারেশন সিনট্যাক্স / মেথড কার্যপ্রণালী ও সময় জটিলতা
সংযোজন lst.append(x)
lst.extend(it)
lst.insert(i, x)
append শেষে একটি উপাদান যোগ করে $O(1)$ সময়ে। extend অন্য লিস্টের সব উপাদান জুড়ে দেয়। insert যেকোনো পজিশনে উপাদান বসায় $O(N)$ সময়ে।
অপসারণ lst.pop([i])
lst.remove(x)
del lst[i]
pop() উপাদান বের করে ও ফেরত দেয় (শেষের উপাদান $O(1)$, মাঝে $O(N)$)। remove(x) প্রথম প্রাপ্ত মান x মুছে ফেলে।
লিস্ট কম্প্রিহেনশন [expr for x in seq if cond] সি-লেভেল দ্রুতগতির এক লাইনের লুপ: [x**2 for x in range(6) if x%2==0] তৈরি করে [0, 4, 16]।
কপির শ্রেণিভেদ অ্যালিয়াসিং বনাম অগভীর কপি বনাম গভীর কপি b = a (একই মেমরি)। b = a.copy() (Shallow copy: বাইরের লিস্ট নতুন, ভেতরের নেস্টেড লিস্ট শেয়ার্ড)। copy.deepcopy(a) (ভেতরের সব অবজেক্ট নতুন করে কপি হয়)।
৪.৪ টাপল (tuple): অপরিবর্তনশীলতার সুবিধা ও প্যাকিং/আনপ্যাকিং

টাপল হলো প্রথম বন্ধনী () দিয়ে ঘেরা অপরিবর্তনীয় সিকোয়েন্স। একটিমাত্র উপাদানের টাপল বানাতে শেষে কমা দেওয়া বাধ্যতামূলক: t = (10,) (কমা না দিলে এটি সাধারণ ইন্টিজার 10 হিসেবে গণ্য হবে)।

  • প্যাকিং ও আনপ্যাকিং: একাধিক মানকে একসাথে বাঁধাকে প্যাকিং বলে: pt = 10, 20। বিপরীতভাবে আলাদা চলকে ভেঙে নেওয়াকে আনপ্যাকিং বলে: x, y = pt। পাইথনে মান অদলবদল (Swap) করা যায় অত্যন্ত সহজে: a, b = b, a।
  • টাপলের সুবিধা: লিস্টের চেয়ে কম মেমরি লাগে এবং গতি বেশি। অপরিবর্তনীয় হওয়ায় এটি সুরক্ষিত এবং ডিকশনারির কী হিসেবে ব্যবহৃত হতে পারে।

৫. হ্যাশ সংকলন: ডিকশনারি ও গাণিতিক সেট অ্যালজেব্রা

৫.১ ডিকশনারি (dict): হ্যাশ টেবিল ও কী (Key)-এর শর্ত

ডিকশনারি হলো কী ও মানের (Key-Value) জোড়া নিয়ে গঠিত পরিবর্তনযোগ্য অ্যাসোসিয়েটিভ অ্যারে। পাইথন ৩.৭+ থেকে ডিকশনারি উপাদানের প্রবেশক্রম (Insertion order) বজায় রাখে।

ডিকশনারি কী (Key)-এর অলঙ্ঘনীয় নিয়ম:

ডিকশনারির কী অবশ্যই অপরিবর্তনযোগ্য এবং হ্যাশেবল (Immutable & Hashable) হতে হবে (যেমন: স্ট্রিং, সংখ্যা বা টাপল)। কোনো মিউটেবল অবজেক্ট (যেমন লিস্ট বা ডিকশনারি) কী হিসেবে ব্যবহার করা যায় না; করলে তৎক্ষণাৎ TypeError: unhashable type ত্রুটি ঘটবে।

প্রধান ডিকশনারি মেথডসমূহ:

  • d.get(key, default): কী না থাকলে KeyError না ঘটিয়ে নিরাপদে ডিফল্ট মান ফেরত দেয়।
  • d.setdefault(key, default): কী থাকলে তার মান দেয়, না থাকলে নতুন কী ও ডিফল্ট মান যুক্ত করে।
  • d.pop(key, [default]): নির্দিষ্ট কী মুছে ফেলে এবং তার মান ফেরত দেয়।
  • d.update(other): অন্য ডিকশনারির উপাদান দিয়ে বর্তমান ডিকশনারি আপডেট করে।
  • d.keys(), d.values(), d.items(): ডিকশনারির কী, মান ও কী-মান জোড়ার ডায়নামিক ভিউ ফেরত দেয়।
  • ডিকশনারি কম্প্রিহেনশন: {k: v for k, v in it} যেমন {x: x**2 for x in range(5)}।
৫.২ সেট (set) ও গাণিতিক সেট অ্যালজেব্রা

সেট হলো অনন্য (Unique) ও অপরিবর্তনীয় উপাদানের একটি পরিবর্তনীয় ও অবিন্যস্ত (Unordered) সংগ্রহ। ফাঁকা সেট তৈরিতে set() ব্যবহার করতে হয় (কারণ {} ফাঁকা ডিকশনারি নির্দেশ করে)।

সেট প্রক্রিয়া অপারেটর মেথড গাণিতিক তাৎপর্য
ইউনিয়ন (সংযোগ) A | B A.union(B) $A$ ও $B$-এর সকল উপাদানের সেট ($A \cup B$)
ইন্টারসেকশন (ছেদ) A & B A.intersection(B) $A$ ও $B$-এর সাধারণ উপাদানের সেট ($A \cap B$)
পার্থক্য বা বিয়োগ A - B A.difference(B) $A$-তে আছে কিন্তু $B$-তে নেই এমন উপাদান ($A \setminus B$)
সিমেট্রিক ডিফারেন্স A ^ B A.symmetric_difference(B) $A$ বা $B$-তে আছে কিন্তু উভয়ের অভিন্ন নয়

৬. মডুলার ফাংশন, LEGB স্কোপ, ফাইল I/O ও এক্সেপশন নিয়ন্ত্রণ

৬.১ মডুলার ফাংশন, আর্গুমেন্ট ও LEGB স্কোপ হায়ারার্কি

পাইথনে ফাংশন হলো ফার্স্ট-ক্লাস সিটিজেন—এদের চলকে রাখা যায়, আর্গুমেন্ট হিসেবে পাঠানো যায় এবং রিটার্ন করা যায়।

  • আর্গুমেন্টের প্রকারভেদ:
    • পজিশনাল আর্গুমেন্ট: ক্রম অনুযায়ী গৃহীত হয়।
    • ডিফল্ট আর্গুমেন্ট: পূর্বে নির্ধারিত মান থাকে (যেমন def calc(rate=0.05):)। মনে রাখতে হবে ডিফল্ট আর্গুমেন্টের পর কোনো সাধারণ আর্গুমেন্ট থাকতে পারে না।
    • পরিবর্তনশীল আর্গুমেন্ট: *args অতিরিক্ত পজিশনাল আর্গুমেন্টকে টাপল আকারে এবং **kwargs অতিরিক্ত কীওয়ার্ড আর্গুমেন্টকে ডিকশনারি আকারে গ্রহণ করে।
  • LEGB স্কোপ রেজোলিউশন নিয়ম: ফাংশনে কোনো নাম খোঁজার সময় পাইথন ৪টি স্তরে অনুসন্ধান চালায়:
    1. L (Local): বর্তমান ফাংশনের অভ্যন্তরীণ লোকাল ভ্যারিয়েবল।
    2. E (Enclosing): বাইরের কোনো মোড়ক ফাংশনের ভ্যারিয়েবল (নেস্টেড ফাংশনে)।
    3. G (Global): মডিউলের শীর্ষ স্তরে থাকা গ্লোবাল ভ্যারিয়েবল বা global ডিক্লেয়ারেশন।
    4. B (Built-in): পাইথনের অন্তর্নির্মিত নামসমূহ (যেমন len, range, print)।
  • global ও nonlocal কিওয়ার্ড: ফাংশনের ভেতর থেকে গ্লোবাল ভ্যারিয়েবল সংশোধন করতে global এবং নেস্টেড ফাংশনে বাইরের ফাংশনের ভ্যারিয়েবল সংশোধন করতে nonlocal ব্যবহার করা হয়।
৬.২ স্থায়ী ফাইল সংরক্ষণ ও কনটেক্সট ম্যানেজার (Context Manager)

ফাইল নিয়ে কাজ করার সর্বোত্তম পদ্ধতি হলো কনটেক্সট ম্যানেজার (with open(...) as f:) ব্যবহার করা, যা কাজ শেষে ফাইলকে স্বয়ংক্রিয়ভাবে ও সুরক্ষিতভাবে বন্ধ করে দেয়:

ফাইল মোড স্ট্রিম প্রকৃতি পয়েন্টারের শুরুর অবস্থান ফাইল না থাকলে আচরণ
'r' শুধু পড়ার জন্য (Text Read) ফাইলের শুরুতে (বাইট 0) FileNotFoundError তৈরি করে।
'w' শুধু লেখার জন্য (Text Write) ফাইলের শুরুতে (আগের তথ্য মুছে দেয়) নতুন ফাইল তৈরি করে।
'a' শেষে সংযোজন (Text Append) ফাইলের একেবারে শেষ প্রান্তে (EOF) নতুন ফাইল তৈরি করে।
'rb' / 'wb' বাইনারি ফাইল (পিকল সিরিয়ালাইজেশন) বাইট লেভেল অফসেট pickle.dump() ও pickle.load() এর সাথে ব্যবহৃত।

ফাইল পয়েন্টার নিয়ন্ত্রণ: f.tell() ফাইলের মধ্যে পয়েন্টারের বর্তমান বাইট অবস্থান নির্দেশ করে। f.seek(offset, whence) পয়েন্টারকে নির্দিষ্ট অবস্থানে সরায় (whence=0 শুরু থেকে, whence=1 বর্তমান অবস্থান থেকে, whence=2 শেষ থেকে)।

৬.৩ এক্সেপশন হ্যান্ডলিং: try, except, else ও finally ব্লক

রানটাইম ত্রুটির কারণে প্রোগ্রাম ক্র্যাশ হওয়া প্রতিরোধ করতে পাইথনের ৪-স্তরের এক্সেপশন মডেল প্রয়োগ করা হয়:

# পূর্ণাঙ্গ এক্সেপশন হ্যান্ডলিং প্যাটার্ন
try:
    with open("data.txt", "r") as f:
        val = int(f.readline())
        ans = 100 / val
except FileNotFoundError:
    print("ত্রুটি: লক্ষ্য ফাইলটি পাওয়া যায়নি।")
except ZeroDivisionError:
    print("ত্রুটি: শূন্য দিয়ে ভাগ করা সম্ভব নয়।")
except ValueError:
    print("ত্রুটি: ফাইলে উপযুক্ত সংখ্যা নেই।")
else:
    # try ব্লক সম্পূর্ণ সফল হলে এটি কার্যকর হবে
    print(f"সফল হিসাব: {ans}")
finally:
    # ত্রুটি ঘটুক বা না ঘটুক এটি নিশ্চিতভাবে চলবে
    print("রিসোর্স ও মেমরি পরিচ্ছন্নতা সম্পন্ন।")

প্রোগ্রামিং সিনট্যাক্স, কমান্ড ও অনুবাদক নীতি

সোর্স কোড (.py) -> AST -> বাইটকোড (.pyc) -> PVM (ceval.c) -> প্রসেসর এক্সিকিউশন
seq[start : stop : step] | দৈর্ঘ্য = max(0, ceil((stop - start) / step))
মিউটেবল: {list, dict, set} | ইমিউটেবল: {int, float, complex, bool, str, tuple, frozenset}
Local (L) -> Enclosing (E) -> Global (G) -> Built-in (B)
'r' (পড়া), 'w' (মুছে নতুন লেখা), 'a' (শেষে সংযোজন), 'r+' (পড়া ও লেখা), 'b' (বাইনারি ফ্ল্যাগ)
try -> (ত্রুটি হলে except) | (ত্রুটি না হলে else) -> finally (সর্বাবস্থায় কার্যকর)

সমাধানকৃত উদাহরণ ও প্রয়োগ (Solved Examples)

উদাহরণ 1
মেমরি রেফারেন্সের সাপেক্ষে পাইথনে মিউটেবল ও ইমিউটেবল ডেটা টাইপের মৌলিক পার্থক্য লেখো। নিচের কোডের দ্বিতীয় প্রিন্ট স্টেটমেন্টের আউটপুট কী হবে এবং কেন ব্যাখ্যা করো: [২ নম্বর] a = [1, 2, 3] b = a a.append(4) print(b) x = 10 y = x x += 5 print(y)
ধাপে ধাপে সমাধান / উত্তর:
ধাপ ১: তাত্ত্বিক পার্থক্য (১ নম্বর) পাইথনে মিউটেবল (পরিবর্তনযোগ্য) ডেটা টাইপের (যেমন list, dict, set) ভেতরের মান নিজস্ব মেমরি ঠিকানায় (id()) সরাসরি পরিবর্তন করা যায়। কিন্তু ইমিউটেবল (অপরিবর্তনীয়) ডেটা টাইপের (যেমন int, float, str, tuple) অভ্যন্তরীণ মান পরিবর্তন করা অসম্ভব; কোনো পরিবর্তনের চেষ্টা করলে হিপ মেমরিতে সম্পূর্ণ নতুন অবজেক্ট তৈরি হয়। ধাপ ২: কোড বিশ্লেষণ ও সঠিক কারণ (১ নম্বর) ১. 'a = [1, 2, 3]': মেমরিতে একটি লিস্ট তৈরি হয়। 'b = a' করায় 'b' সেই একই মেমরি নির্দেশ করে। লিস্ট মিউটেবল হওয়ায় 'a.append(4)' মূল লিস্টটিকে [1, 2, 3, 4]-এ রূপান্তর করে। ফলে 'print(b)' দিলে [1, 2, 3, 4] প্রদর্শিত হয়। ২. 'x = 10': মেমরিতে 10 তৈরি হয় এবং 'y = x' করায় 'y'-ও 10 নির্দেশ করে। কিন্তু ইন্টিজার ইমিউটেবল হওয়ায় 'x += 5' করলে নতুন সংখ্যা 15 তৈরি হয়ে 'x'-এ যুক্ত হয়, কিন্তু 'y' আগের 10-এই বহাল থাকে। তাই 'print(y)' এর মান হবে 10। চূড়ান্ত আউটপুট: [1, 2, 3, 4] 10
উদাহরণ 2
যদি s = 'WBCHSE_COMPUTER_SCIENCE_2026' হয়, তবে নিচের স্লাইসিং ও মেথডের আউটপুট প্রতি ধাপের ইনডেক্স উল্লেখসহ নির্ণয় করো: [৩ নম্বর] (a) s[7:15] (b) s[::-3] (c) s.split('_')[1].lower()
ধাপে ধাপে সমাধান / উত্তর:

ধাপে ধাপে সমাধান:

(a) s[7:15] এর মূল্যায়ন: [১ নম্বর]

  • সূত্র: s[start:stop] ইনডেক্স 7 থেকে শুরু করে ইনডেক্স 14 পর্যন্ত নেবে (stop ইনডেক্স 15 বাদ যাবে)।
  • ইনডেক্স 7 = 'C', 8 = 'O', 9 = 'M', 10 = 'P', 11 = 'U', 12 = 'T', 13 = 'E', 14 = 'R' ।
  • ফলাফল: 'COMPUTER'

(b) s[::-3] এর মূল্যায়ন: [১ নম্বর]

  • সূত্র: ঋণাত্মক ধাপ (-3) থাকায় শেষ অক্ষর s[-1] অর্থাৎ ইনডেক্স 28 থেকে ৩ ঘর পিছিয়ে অক্ষর নেবে।
  • ইনডেক্সসমূহ: 28 ('6'), 25 ('0'), 22 ('E'), 19 ('I'), 16 ('_'), 13 ('E'), 10 ('P'), 7 ('C'), 4 ('S'), 1 ('B')।
  • ফলাফল: '60EI_EPCSB'

(c) s.split('_')[1].lower() এর মূল্যায়ন: [১ নম্বর]

  • 's.split('_')' আন্ডারস্কোর দিয়ে ভেঙে লিস্ট তৈরি করে: ['WBCHSE', 'COMPUTER', 'SCIENCE', '2026']।
  • ইনডেক্স [1] এর মান হলো 'COMPUTER'।
  • '.lower()' মেথড একে ছোট হাতের অক্ষরে পরিণত করে: 'computer'।
  • ফলাফল: 'computer'
উদাহরণ 3
পাইথনে একটি ফাংশন 'char_frequency(text)' লেখো যা একটি স্ট্রিং ইনপুট নেবে, সমস্ত স্পেস ও চিহ্ন বাদ দিয়ে ছোট হাতের অক্ষরে রূপান্তর করবে এবং ডিকশনারি ব্যবহারের মাধ্যমে প্রতিটি বর্ণের পুনরাবৃত্তির সংখ্যা (Frequency) হিসাব করে ফেরত দেবে। [৩ নম্বর]
ধাপে ধাপে সমাধান / উত্তর:

আদর্শ পাইথন প্রোগ্রাম:

def char_frequency(text): """ প্রতিটি অ্যালফাবেটের ফ্রিকোয়েন্সি গণনা করে ডিকশনারি আকারে ফেরত দেয়। """ freq = {} for char in text.lower(): if char.isalpha(): # কেবল বর্ণমালা নির্বাচন করা হচ্ছে # ডিকশনারির get() মেথড দিয়ে O(1) সময়ে হিসাব freq[char] = freq.get(char, 0) + 1 return freq

ড্রাইভার কল ও টেস্ট:

sample_text = 'Python Class 12 WBCHSE!' result = char_frequency(sample_text) print(result)

মূল্যায়ন রুব্রিক (৩ নম্বর):

  • স্ট্রিংকে লোয়ারকেস করা ও লুপ চালানো (১ নম্বর)।
  • 'char.isalpha()' দিয়ে স্পেস ও সংখ্যা বা চিহ্ন বাদ দেওয়া (১ নম্বর)।
  • ডিকশনারির 'freq.get(char, 0) + 1' মেথডের মাধ্যমে নির্ভুল গণনা (১ নম্বর)। আউটপুট: {'p': 1, 'y': 1, 't': 1, 'h': 2, 'o': 1, 'n': 1, 'c': 2, 'l': 1, 'a': 1, 's': 3, 'w': 1, 'b': 1, 'e': 1}
উদাহরণ 4
(a) নেস্টেড লিস্ট কম্প্রিহেনশন ব্যবহার করে একটি M x N ম্যাট্রিক্সের ট্রান্সপোজ (সারি ও স্তম্ভের স্থানান্তর) তৈরি করো। [২ নম্বর] (b) লিস্ট কম্প্রিহেনশন দিয়ে ২ থেকে ৫০ পর্যন্ত সমস্ত মৌলিক সংখ্যার একটি তালিকা এক লাইনের কোডে তৈরি করো। [২ নম্বর]
ধাপে ধাপে সমাধান / উত্তর:

অংশ (a): ম্যাট্রিক্স ট্রান্সপোজ [২ নম্বর]

matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12] ]

এক লাইনের নেস্টেড লিস্ট কম্প্রিহেনশন:

transposed = [[row[col] for row in matrix] for col in range(len(matrix[0]))] print(transposed)

আউটপুট: [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

নম্বর বিভাজন: কলাম লুপ 'range(len(matrix[0]))' (১ নম্বর); ভেতরের রো এক্সট্রাকশন 'row[col] for row in matrix' (১ নম্বর)।


অংশ (b): মৌলিক সংখ্যা ফিল্টারিং [২ নম্বর]

এক লাইনের প্রাইম ফিল্টার কম্প্রিহেনশন:

primes = [n for n in range(2, 51) if all(n % d != 0 for d in range(2, int(n**0.5) + 1))] print(primes)

আউটপুট: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

নম্বর বিভাজন: সীমানা range(2, 51) (১ নম্বর); নেস্টেড all() ও উৎপাদক যাচাই (১ নম্বর)।

উদাহরণ 5
কনটেক্সট ম্যানেজার ('with open') ব্যবহার করে একটি পাইথন স্ক্রিপ্ট লেখো যা নিম্নলিখিত কাজগুলো করবে: [৪ নম্বর] ১. 'input_log.txt' নামক একটি টেক্সট ফাইল পড়বে। ২. মোট লাইন সংখ্যা, মোট শব্দ সংখ্যা এবং নিউলাইন বাদে মোট অক্ষর সংখ্যা গণনা করবে। ৩. 'ERROR:' দিয়ে শুরু হওয়া সমস্ত ইউনিক (অনন্য) লাইন শনাক্ত করে প্রিন্ট করবে। ৪. 'FileNotFoundError' এবং সাধারণ 'IOError' যথাযথভাবে হ্যান্ডেল করবে।
ধাপে ধাপে সমাধান / উত্তর:

আদর্শ পাইথন ফাইল হ্যান্ডলিং কোড:

def analyze_log_file(filename): total_lines = 0 total_words = 0 total_chars = 0 error_lines = set() # ইউনিক লাইনের জন্য সেট ব্যবহার

try:
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            total_lines += 1
            cleaned = line.rstrip('\r\n')
            total_chars += len(cleaned)
            words = cleaned.split()
            total_words += len(words)
            
            if cleaned.startswith('ERROR:'):
                error_lines.add(cleaned)

    print(f'ফাইল নাম: {filename}')
    print(f'মোট লাইন সংখ্যা: {total_lines}')
    print(f'মোট শব্দ সংখ্যা: {total_words}')
    print(f'মোট অক্ষর সংখ্যা: {total_chars}')
    print(f'ইউনিক ত্রুটিসমূহ ({len(error_lines)}টি):')
    for err in sorted(error_lines):
        print(f'  - {err}')

except FileNotFoundError:
    print(f'ত্রুটি: "{filename}" ফাইলটি মেমরিতে খুঁজে পাওয়া যায়নি।')
except IOError as e:
    print(f'I/O সিস্টেম ত্রুটি: {e}')

ড্রাইভার কল:

analyze_log_file('input_log.txt')

মূল্যায়ন রুব্রিক (৪ নম্বর):

  • 'with open' কনটেক্সট ম্যানেজার ব্যবহার (১ নম্বর)।
  • লাইন, শব্দ ও অক্ষর সংখ্যার সঠিক গণনা (১ নম্বর)।
  • 'startswith('ERROR:')' দিয়ে সেট সংরক্ষণ (১ নম্বর)।
  • FileNotFoundError ও IOError ব্লকের সুবিন্যস্ত ব্যবহার (১ নম্বর)।
উদাহরণ 6
একটি পরিসংখ্যামূলক পাইথন ফাংশন 'compute_summary(*data, **options)' তৈরি করো যা নিম্নলিখিত প্রযুক্তিগত শর্ত পূরণ করবে: [৫ নম্বর] ১. '*data' দিয়ে যেকোনো সংখ্যক সংখ্যা গ্রহণ করবে। ২. '**options' দিয়ে 'precision' (ডিফল্ট 2) কীওয়ার্ড গ্রহণ করবে। ৩. যদি কোনো আর্গুমেন্ট না পাঠানো হয়, তবে কাস্টম এক্সেপশন 'EmptyDatasetError' রেইজ করবে। ৪. গড় (mean), ভ্যারিয়্যান্স (variance) এবং স্ট্যান্ডার্ড ডেভিয়েশন (standard_deviation) বের করে ডিকশনারি আকারে ফেরত দেবে। ৫. একটি 'try...except...finally' ড্রাইভার ব্লকের মাধ্যমে কোডের নির্ভুল কার্যকারিতা প্রমাণ করো।
ধাপে ধাপে সমাধান / উত্তর:

সম্পূর্ণ ও সুরক্ষিত পাইথন প্রোগ্রাম:

ধাপ ১: কাস্টম এক্সেপশন শ্রেণি তৈরি

class EmptyDatasetError(Exception): """খালি ডেটাসেটের জন্য কাস্টম ব্যতিক্রম।""" pass

ধাপ ২: পরিসংখ্যামূলক ফাংশন বাস্তবায়ন

def compute_summary(*data, **options): if not data: raise EmptyDatasetError('ডেটাসেটে কোনো সংখ্যা প্রদান করা হয়নি!')

for x in data:
    if not isinstance(x, (int, float)):
        raise TypeError(f'অবৈধ উপাদান: {x}। সমস্ত মান সংখ্যা হতে হবে।')
        
precision = options.get('precision', 2)
n = len(data)
mean_val = sum(data) / n
variance_val = sum((x - mean_val) ** 2 for x in data) / n
std_dev = variance_val ** 0.5

return {
    'count': n,
    'mean': round(mean_val, precision),
    'variance': round(variance_val, precision),
    'standard_deviation': round(std_dev, precision)
}

ধাপ ৩: ড্রাইভার ব্লক ও এক্সেপশন পরীক্ষা

def main(): tests = [ (10, 20, 30, 40, 50), (), # EmptyDatasetError ট্রিগার করবে (5, 'ভুল_ইনপুট', 15) # TypeError ট্রিগার করবে ]

for i, t in enumerate(tests, 1):
    print(f'\n--- টেস্ট কেস {i} ---')
    try:
        res = compute_summary(*t, precision=3)
        print(f'হিসাব সফল: {res}')
    except EmptyDatasetError as e:
        print(f'[ধৃত ব্যতিক্রম]: {e}')
    except TypeError as e:
        print(f'[ধৃত ব্যতিক্রম]: {e}')
    finally:
        print(f'টেস্ট কেস {i}-এর নির্বাহ সমাপ্ত।')

if name == 'main': main()

নম্বর বণ্টন (৫ নম্বর):

  • Exception থেকে ইনহেরিট করে কাস্টম ক্লাস তৈরি (১ নম্বর)।
  • *data ও **options এর সঠিক ব্যবহার (১ নম্বর)।
  • খালি ডেটাসেটে 'raise EmptyDatasetError' প্রয়োগ (১ নম্বর)।
  • গড়, ভ্যারিয়্যান্স ও স্ট্যান্ডার্ড ডেভিয়েশনের সঠিক গাণিতিক সূত্র (১ নম্বর)।
  • সম্পূর্ণ try...except...finally ড্রাইভার ব্লক (১ নম্বর)।

সাধারণ ভুলত্রুটি ও সতর্কতা (Common Traps)

সাধারণ ভুল ধারণা

ডিফল্ট আর্গুমেন্টে মিউটেবল অবজেক্ট ব্যবহার: def add_item(val, target=[])

সঠিক পদ্ধতি ও সমাধান

ডিফল্ট হিসেবে সর্বদা 'None' ব্যবহার করো: def add_item(val, target=None): if target is None: target = []

সাধারণ ভুল ধারণা

মান সমতা ('==') এবং মেমরি আইডেন্টিটি ('is') গুলিয়ে ফেলা

সঠিক পদ্ধতি ও সমাধান

মান পরীক্ষার জন্য সর্বদা '==' ব্যবহার করো। কেবল None পরীক্ষার ক্ষেত্রে 'if val is None:' ব্যবহার করো।

সাধারণ ভুল ধারণা

for লুপ দিয়ে ইটারেশন চলাকালীন সরাসরি সেই লিস্টের উপাদান ডিলিট করা

সঠিক পদ্ধতি ও সমাধান

লিস্টের একটি অগভীর কপির ওপর লুপ চালাও: 'for item in my_list[:]:' অথবা লিস্ট কম্প্রিহেনশন দিয়ে নতুন লিস্ট গঠন করো।

সাধারণ ভুল ধারণা

range() এবং স্লাইসিংয়ে অফ-বাই-ওয়ান (Off-by-one) সীমানা ভুল

সঠিক পদ্ধতি ও সমাধান

N পর্যন্ত মান পেতে হলে স্টপ মান N + 1 দিতে হবে: 'range(1, 11)' দিলে ১ থেকে ১০ পর্যন্ত মান পাওয়া যায়।

সাধারণ ভুল ধারণা

একবার read() করার পর পুনরায় ফাইল পড়ার চেষ্টা করা

সঠিক পদ্ধতি ও সমাধান

পুনরায় পড়তে হলে 'file.seek(0)' কমান্ড দিয়ে ফাইল পয়েন্টারকে শুরুতে ফিরিয়ে আনো।

চিত্রগত ব্যাখ্যা ও মডেল

পাইথনে প্রোগ্রামিং : স্থাপত্য ও নির্বাহ পাইপলাইন WBCHSE দ্বাদশ শ্রেণি কম্পিউটার সায়েন্স (অধ্যায় ১) — অভ্যন্তরীণ আর্কিটেকচার ও মেমরি মডেল WBCHSE CS • CH 1 ১ম স্তর: CPython কম্পাইলেশন ও PVM এক্সিকিউশন সোর্স কোড থেকে বাইটকোড ও ভার্চুয়াল মেশিন • সোর্স ফাইল (.py) -> CPython কম্পাইলার -> AST রূপান্তর • মধ্যবর্তী বাইটকোড (.pyc) pycache ফোল্ডারে সংরক্ষিত • পাইথন ভার্চুয়াল মেশিন (PVM) স্ট্যাক-ভিত্তিক ইন্টারপ্রেটার • প্ল্যাটফর্ম স্বাধীনতা: যেকোনো OS-এ সমভাবে কার্যকর Q1 ২য় স্তর: ডায়নামিক টাইপিং ও অবজেক্ট মেমরি মডেল মিউটেবিলিটি, রেফারেন্স কাউন্টিং ও গারবেজ কালেকশন • প্রতিটি চলক হলো মেমরির একটি পয়েন্টার বা রেফারেন্স • পরিবর্তনীয় (Mutable): list, dict, set — ইন-প্লেস আপডেট • অপরিবর্তনীয় (Immutable): int, float, str, tuple — নিরাপদ • id() ও type() ফাংশন; '==' বনাম 'is' আইডেন্টিটি যাচাই Q2 পাইথন কম্পিউটেশনাল ইঞ্জিন: ব্যাখ্যাভিত্তিক • গতিশীল • অবজেক্ট-ওরিয়েন্টেড BYTECODE (.pyc) • PVM ENGINE • DYNAMIC TYPING • LEGB SCOPE • RESILIENT I/O ৩য় স্তর: সিকোয়েন্স ও হ্যাশ ম্যাপিং ডেটা স্ট্রাকচার লিস্ট, টাপল, ডিকশনারি ও সেট কম্প্রিহেনশন • স্ট্রিং ও লিস্ট স্লাইসিং: s[start:stop:step], s[::-1] • টাপল প্যাকিং ও আনপ্যাকিং; ডিকশনারি কী হ্যাশাবিলিটি শর্ত • লিস্ট ও ডিকশনারি কম্প্রিহেনশন: গতিশীল ও সুসংহত কোড • সেট অ্যালজেব্রা: ইউনিয়ন, ইন্টারসেকশন ও সাবসেট পরীক্ষা Q3 ৪র্থ স্তর: মডুলার ফাংশন, ফাইল I/O ও ব্যতিক্রম নিয়ন্ত্রণ LEGB স্কোপ, কনটেক্সট ম্যানেজার ও ট্রাই-এক্সেপ্ট • ফাংশন প্যারামিটার: পজিশনাল, ডিফল্ট, *args ও **kwargs • নেমস্পেস রেজোলিউশন: Local -> Enclosing -> Global -> Built-in • 'with open(...) as f:' — স্বয়ংক্রিয় রিসোর্স ও ফাইল ক্লোজিং • ট্রাই-এক্সেপ্ট-এলস-ফাইনালি (try-except-else-finally) ব্যতিক্রম মডেল Q4

স্ব-মূল্যায়ন অনুশীলন (Check Your Understanding)

মূল ধারণাগত স্পষ্টতা যাচাই করার জন্য অনুশীলন প্রশ্ন। উত্তর দেখার আগে নিজে সমাধান করার চেষ্টা করো।

1
নিচের কোডের আউটপুট কী হবে এবং কেন ব্যাখ্যা করো: def add_val(x, l=[]): l.append(x) return l print(add_val(10)) print(add_val(20, [])) print(add_val(30))
উত্তর ও ব্যাখ্যা দেখুন
উত্তর: আউটপুট: [10] [20] [10, 30] ব্যাখ্যা: প্রথম কলে ডিফল্ট লিস্টে 10 যোগ হয়ে [10] হয়। দ্বিতীয় কলে নতুন স্পষ্ট খালি লিস্ট [] পাঠানোয় ডিফল্ট লিস্ট অক্ষত থাকে এবং [20] ফিরে আসে। তৃতীয় কলে পুনরায় সেই ডিফল্ট লিস্টটি ব্যবহৃত হয় যাতে আগেই [10] ছিল, ফলে 30 যোগ হয়ে [10, 30] হয়।
ডিফল্ট আর্গুমেন্ট ফাংশন সংজ্ঞায়নের সময় মাত্র একবার মেমরিতে তৈরি হয়।
2
পাইথনে অগভীর কপি (Shallow copy) এবং গভীর কপির (Deep copy) মধ্যে পার্থক্য কী? নেস্টেড লিস্টের উদাহরণসহ লেখো।
উত্তর ও ব্যাখ্যা দেখুন
উত্তর: অগভীর কপি (b = a.copy()) কেবল বাইরের লিস্টের নতুন মেমরি তৈরি করে, কিন্তু ভেতরের নেস্টেড অবজেক্টগুলোর রেফারেন্স একই রাখে। গভীর কপি (copy.deepcopy(a)) ভেতরের সমস্ত উপাদানকে রিকার্সিভভাবে নতুন করে কপি করে। উদাহরণ: a = [[10]]; b = a.copy(); b[0].append(20); print(a) দিলে [[10, 20]] দেখাবে, কারণ উভয়ের ভেতরের লিস্ট অভিন্ন।
নেস্টেড লিস্ট a = [[1, 2], [3, 4]] বিবেচনা করো। ভেতরের উপাদান পরিবর্তন করলে কী ঘটে?
3
পাইথনে (10,) একটি টাপল কিন্তু (10) একটি ইন্টিজার কেন?
উত্তর ও ব্যাখ্যা দেখুন
উত্তর: পাইথনে প্রথম বন্ধনী গাণিতিক রাশিমালার অগ্রাধিকার বোঝাতেও ব্যবহৃত হয় (যেমন (2 + 3) * 4)। তাই একটি উপাদানের টাপল বোঝাতে কমা বাধ্যতামূলক: (10,) একটি টাপল নির্দেশ করে, কিন্তু (10) বন্ধনীযুক্ত সাধারণ ইন্টিজার 10 হিসেবে গণ্য হয়।
পাইথনে বন্ধনী গাণিতিক অপারেটরের গ্রুপ তৈরির কাজেও ব্যবহৃত হয়।
4
ডিকশনারি কম্প্রিহেনশন ব্যবহার করে 'd = {"x": 10, "y": 20, "z": 30}' ডিকশনারিটির কী ও মান অদলবদল (Invert) করার একটি পাইথন এক্সপ্রেশন লেখো।
উত্তর ও ব্যাখ্যা দেখুন
উত্তর: inverted = {val: key for key, val in d.items()} ফলাফল: {10: 'x', 20: 'y', 30: 'z'} (শর্ত: ডিকশনারির মানসমূহ অবশ্যই অনন্য ও হ্যাশেবল হতে হবে)।
d.items() এর ওপর লুপ চালিয়ে মানকে কী এবং কী-কে মান হিসেবে বসাও।
5
এক্সেপশন হ্যান্ডলিংয়ে 'finally' ব্লকের ভূমিকা কী? try ব্লকে 'return' থাকলেও কি finally কার্যকর হয়?
উত্তর ও ব্যাখ্যা দেখুন
উত্তর: 'finally' ব্লকের মূল কাজ হলো ফাইল, ডাটাবেস বা নেটওয়ার্ক সংযোগের মতো সিস্টেম রিসোর্স নিশ্চিতভাবে বন্ধ করা। হ্যাঁ, এমনকি try ব্লকে 'return' স্টেটমেন্ট থাকলেও ফাংশন থেকে বের হওয়ার ঠিক পূর্বমুহূর্তে finally ব্লকটি নিশ্চিতভাবে কার্যকর হবে।
রিসোর্স বন্ধ করার প্রয়োজনীয়তার কথা চিন্তা করো।
অধ্যায় পড়া শেষ হয়েছে?
অনুশীলন শুরু করো

অনলাইন মক টেস্ট দিয়ে প্রস্তুতি যাচাই করো

পশ্চিমবঙ্গ মধ্যশিক্ষা পর্ষদ (WBBSE) পাঠ্যক্রম অনুযায়ী বহু বিকল্পীয় প্রশ্ন (MCQ) সমাধান করো। তাৎক্ষণিক ফলাফল, সঠিক ব্যাখ্যা এবং নিজের স্কোর জেনে নাও।

STAY UPDATED

Get the Latest Updates

New test series, syllabus updates, exam notifications and more.

Syllabus
Updates
Exam
Alerts
Study
Resources