অধ্যায় 3 · আসল প্রোগ্রাম লেখা
ক্লাস ও অবজেক্ট
- পৃষ্ঠা 12 / 20
- 4 মিনিট পড়া
এ পর্যন্ত ডেটা আর তার ওপর কাজ করা ফাংশন আলাদা আলাদা থেকেছে। ক্লাস দুটোকে একসাথে বাঁধে: এটা এক ধরনের জিনিসের বর্ণনা — একটা কথোপকথন, একটা মডেল, একটা ডকুমেন্ট — তার ভেতরের ডেটা আর সে যে কাজগুলো করতে পারে তা সহ। ক্লাস থেকে বানানো প্রতিটা আসল জিনিস হলো একটা অবজেক্ট (বা ইনস্ট্যান্স)। যে AI লাইব্রেরিই ব্যবহার করুন, তা ক্লাস দিয়ে গড়া: OpenAI() একটা ক্লায়েন্ট অবজেক্ট বানায়, আর client.responses.create(...) তার একটা মেথড ডাকে।
শুরু থেকে একটা ক্লাস
class Conversation:
"""একটা চ্যাট ইতিহাস, যা ল্যাঙ্গুয়েজ মডেলে পাঠানো যায়।"""
def __init__(self, system_prompt):
self.messages = [{"role": "system", "content": system_prompt}]
def add_user(self, text):
self.messages.append({"role": "user", "content": text})
def add_assistant(self, text):
self.messages.append({"role": "assistant", "content": text})
def last_reply(self):
for message in reversed(self.messages):
if message["role"] == "assistant":
return message["content"]
return None
def __len__(self):
return len(self.messages)
def __repr__(self):
return f"Conversation({len(self)} messages)"
chat = Conversation("You are a patient Python tutor.")
chat.add_user("What is a list?")
chat.add_assistant("An ordered, changeable collection of items.")
print(chat)
print(chat.last_reply())
other = Conversation("You translate English into Bangla.")
print(len(chat), len(other)) # প্রতিটা অবজেক্টের নিজস্ব messagesConversation(3 messages)
An ordered, changeable collection of items.
3 1ধাপে ধাপে:
class Conversation:ক্লাসটা সংজ্ঞায়িত করে। ক্লাসের নাম লেখা হয়CapitalisedWordsধরনে।Conversation("...")দিয়ে অবজেক্ট বানালে__init__আপনাআপনি চলে। এটা অবজেক্টের শুরুর ডেটা সাজায়।selfহলো অবজেক্টটা নিজেই।self.messagesএকটা অ্যাট্রিবিউট — এই নির্দিষ্ট অবজেক্টে রাখা ডেটা। তাইchatআরother-এর আলাদা আলাদা messages আছে।- ক্লাসের ভেতরে সংজ্ঞায়িত ফাংশন হলো মেথড। প্রথম প্যারামিটার সবসময়
self, কিন্তু আপনি সেটা দেন না:chat.add_user("…")নিজেইselfবসিয়ে দেয়। __len__আর__repr__-এর মতো দুই আন্ডারস্কোরওয়ালা নাম হলো বিশেষ মেথড, যা আপনার ক্লাসকে Python-এর সাথে জুড়ে দেয়:len(chat)ডাকে__len__, আরprint(chat)ব্যবহার করে__repr__।
উত্তরাধিকার (inheritance): ক্লাসের একটা পরিবার
একটা ক্লাস আরেকটা থেকে উত্তরাধিকার নিতে পারে, তার সব অ্যাট্রিবিউট আর মেথড পেয়ে যায়, তারপর যে অংশগুলো আলাদা সেগুলো বদলে (override) দিতে পারে:
class Model:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name}: {self.kind()}"
def kind(self):
return "a generic model"
class ChatModel(Model):
def kind(self): # প্যারেন্টের রূপটা বদলে দেওয়া
return "turns messages into a reply"
class EmbeddingModel(Model):
def kind(self):
return "turns text into a list of numbers"
for m in [ChatModel("gpt-5.5"), EmbeddingModel("text-embedding-3-small")]:
print(m.describe())
print(isinstance(ChatModel("x"), Model))gpt-5.5: turns messages into a reply
text-embedding-3-small: turns text into a list of numbers
Truedescribe() লেখা হয়েছে একবারই, Model-এ, তবু প্রতিটা সাবক্লাস নিজের ঠিক বর্ণনা দিচ্ছে, কারণ self.kind() আসল অবজেক্টের নিজস্ব রূপটাই ডাকে। আগের পাতায় আপনি উত্তরাধিকার ব্যবহার করেছেন: class TemporaryAPIError(Exception)।
ডেটাক্লাস: মূলত ডেটা রাখার ক্লাস
অনেক ক্লাস শুধু কয়েকটা নাম দেওয়া মান রাখে — সেটিং, একটা সার্চ ফলাফল, একটা পার্স করা উত্তর। @dataclass ডেকোরেটর ঘরগুলোর তালিকা থেকে আপনার হয়ে __init__, __repr__ আর == লিখে দেয়:
from dataclasses import dataclass, field
@dataclass
class RequestSettings:
model: str
temperature: float = 0.7
max_output_tokens: int = 500
stop: list[str] = field(default_factory=list)
def cheaper(self):
return RequestSettings(self.model, self.temperature, self.max_output_tokens // 2, self.stop)
s = RequestSettings("gpt-5.5", temperature=0.2)
print(s)
print(s.cheaper())
print(s == RequestSettings("gpt-5.5", 0.2))RequestSettings(model='gpt-5.5', temperature=0.2, max_output_tokens=500, stop=[])
RequestSettings(model='gpt-5.5', temperature=0.2, max_output_tokens=250, stop=[])
Trueপ্রতিটা ঘরের পরে : str, : float হলো টাইপ হিন্ট (পাতা ১৮-তে আরও আছে)। লিস্টের ডিফল্টের জন্য field(default_factory=list) দিন — পাতা ৭-এর সেই পরিবর্তনযোগ্য-ডিফল্টের ফাঁদ।
কখন ক্লাস লিখবেন?
- কিছু ডেটা আর তার ওপরের ফাংশন সবসময় একসাথে চলে (একটা কথোপকথন আর তার মেসেজ) — ক্লাস লিখুন।
- নিজস্ব অবস্থাসহ একই রকম কয়েকটা অবজেক্ট লাগবে — ক্লাস লিখুন।
- শুধু একটা হিসাব, যা ইনপুট নিয়ে আউটপুট দেয় — ফাংশনই যথেষ্ট। সবকিছুকে ক্লাস হতে হবে না।
নিজে চেষ্টা করুন
Conversation-এword_count()মেথড যোগ করুন, যা সব মেসেজের মোট শব্দসংখ্যা ফেরত দেয়।title,urlআরscoreনিয়ে একটাSearchResultডেটাক্লাস লিখুন, তিনটা বানিয়ে স্কোর অনুযায়ী সবচেয়ে ভালোটা প্রিন্ট করুন।Conversationথেকে উত্তরাধিকার নেওয়া একটাBanglaTutorক্লাস বানান, যা সবসময় একটা বাংলা system প্রম্পট দিয়ে শুরু হয়।