ক্

ক্লাস মধ্যে Python

49টি অনুশীলনী

ক্লাস সম্পর্কে

Classes ডেটার সাথে বিহেভিয়ারের সমন্বয় ঘটায়। একসাথে বাঁধা ডেটা ও বিহেভিয়ারের কপি বা instances তৈরি করতে ক্লাস ব্যবহার করা হয়, যেগুলোকে সাধারণত objects বলা হয়। অবজেক্ট বাস্তব জগতের সত্তাকে (যেমন গাড়ি বা বিড়াল) বোঝাতে পারে, আবার আরও বিমূর্ত ধারণাকেও (যেমন ইন্টিজার, যানবাহন বা স্তন্যপায়ী)। একটি অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং (OOP) পদ্ধতির অবিচ্ছেদ্য অংশ ক্লাস, যেখানে প্রোগ্রামারকে একটি সমস্যাকে এক বা একাধিক অবজেক্ট হিসেবে মডেল করার কথা ভাবতে বলা হয়, যেসব অবজেক্ট একে অন্যের সাথে যোগাযোগ করে, স্টেট ধরে রাখে এবং ডেটার উপর কাজ করে।

ক্লাস

ক্লাস হলো নতুন অবজেক্ট টাইপ-এর সংজ্ঞা, যা থেকে অবজেক্টের নতুন instances তৈরি হয়। এগুলো প্রায়ই ডেটা (যা fields, attributes, properties, data members বা variables নামে পরিচিত) এবং সেই ডেটার উপর কাজ করা কোড বা ফাংশন (যা methods নামে পরিচিত) একসাথে বেঁধে রাখে। এই অর্থে ক্লাস হলো একটি নকশা বা কিছু নির্দেশনা, যা থেকে একই ধরনের অনেক অবজেক্ট গড়ে তোলা ও ব্যবহার করা যায়। একটি জটিল প্রোগ্রামে অনেক ক্লাস থাকতে পারে, যার প্রত্যেকে বিভিন্ন ধরনের অনেক অবজেক্ট তৈরি করে। ক্লাস থেকে একটি অবজেক্ট গড়ে তোলা ও কাস্টমাইজ করার প্রক্রিয়াকে instantiation বলা হয় (বা ক্লাসের একটি ইনস্ট্যান্স তৈরি করা)।

Python-এ একটি ক্লাস সংজ্ঞায়িত করা সহজ:

class MyClass:
    # Class body goes here

ক্লাস অ্যাট্রিবিউট

ক্লাসের বডিতে ক্লাস ফিল্ড (যা প্রপার্টি, অ্যাট্রিবিউট, ডেটা মেম্বার বা ভ্যারিয়েবল নামেও পরিচিত) যোগ করা যায়।

class MyClass:
    number = 5
    string = "Hello!"

MyClass-এর একটি ইনস্ট্যান্স (অবজেক্ট) তৈরি করে একটি নামের সাথে বেঁধে রাখা যায়:

>>> new_object = MyClass()

# Class is instantiated and resulting object is bound to the "new_object" name (variable).
# Note: the object address 'at 0x15adc55b0' will vary by computer.
>>> new_object
<__main__.MyClass at 0x15adc55b0>

একটি ক্লাস থেকে তৈরি সব অবজেক্ট (বা ইনস্ট্যান্স) জুড়ে Class attributes ভাগাভাগি হয়, এবং dot notation দিয়ে সেগুলো ব্যবহার করা যায়। অর্থাৎ অবজেক্টের নামের পরে ও অ্যাট্রিবিউটের নামের আগে বসানো একটি .:

>>> new_object = MyClass()

# Accessing the class attribute "number" via dot-notation.
>>> new_object.number
5

# Accessing the class attribute "string" via dot-notation.
>>> new_object.string
'Hello!'

# Instantiating an additional object and binding it to the "second_new_object" name.
>>> second_new_object = MyClass()

>>> second_new_object
<__main__.MyClass at 0x15ad99970>

# Second_new_object shares the same class attributes as new_object.
>>> new_object.number == second_new_object.number
True

ক্লাস অ্যাট্রিবিউট ক্লাসের বডিতেই, অন্য যেকোনো মেথডের আগে সংজ্ঞায়িত করা হয়। এগুলোর মালিক ক্লাস নিজেই, তাই এগুলো ইনস্ট্যান্স জুড়ে ভাগাভাগি করা যায়। যেহেতু ক্লাসের সব ইনস্ট্যান্স এই অ্যাট্রিবিউট ভাগ করে নেয়, তাই ক্লাস থেকেই সরাসরি এগুলোর মান ব্যবহার ও পরিবর্তন করা যায়। ক্লাস অ্যাট্রিবিউটের মান বদলালে ক্লাস থেকে তৈরি সব অবজেক্টেরই মান বদলে যায়:

>>> obj_one = MyClass()
>>> obj_two = MyClass()

# Accessing a class attribute from an object.
>>> obj_two.number
5

# Accessing the class attribute from the class itself.
>>> MyClass.number
5

# Modifying the value of the "number" class attribute.
>>> MyClass.number = 27

# Modifying the "number" class attribute changes the "number" attribute for all objects.
>>> obj_one.number
27

>>> obj_two.number
27

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

__init__() দিয়ে অবজেক্ট ইনস্ট্যান্টিয়েশন কাস্টমাইজ করা

বিশেষ "ডান্ডার মেথড" ("ডাবল আন্ডারস্কোর মেথড"-এর সংক্ষিপ্ত রূপ) __init__() দিয়ে ক্লাস ইনস্ট্যান্স কাস্টমাইজ করা হয়, আর এটি দিয়ে অবজেক্টের ইনস্ট্যান্স অ্যাট্রিবিউট বা প্রপার্টি ইনিশিয়ালাইজ করা যায়। ইনস্ট্যান্স অ্যাট্রিবিউট ইনিশিয়ালাইজ করার ভূমিকার কারণে __init__()-কে class constructor বা initializer-ও বলা হয়। __init__() একটি আবশ্যক প্যারামিটার নেয়, যার নাম self, এবং যা নতুন করে তৈরি হওয়া অবজেক্টকে নির্দেশ করে। এরপর self প্যারামিটারের পরে __init__()-এর আর্গুমেন্ট হিসেবে ইনস্ট্যান্স অ্যাট্রিবিউট বা প্রপার্টির ডেটা পাঠানো যায়।

নিচে MyClass-এ location_x ও location_y নামের ইনস্ট্যান্স অ্যাট্রিবিউট যোগ করা হয়েছে। দেখতে পাচ্ছেন, __init__()-এ পাঠানো location (একটি টাপল) আর্গুমেন্টের প্রথম ও দ্বিতীয় ইনডেক্সে দুটি অ্যাট্রিবিউট অ্যাসাইন করা হয়েছে। ক্লাসটি ইনস্ট্যান্টিয়েট করে একটি অবজেক্ট তৈরি করলেই ক্লাস ইনস্ট্যান্সের location_x ও location_y অ্যাট্রিবিউট ইনিশিয়ালাইজ হয়ে যাবে:

class MyClass:
    # These are class attributes, variables, or fields.
    number = 5
    string = "Hello!"

    # This is the class "constructor", with a "location" parameter that is a tuple.
    def __init__(self, location):

        # This is an instance or object property, attribute, or variable.
        # Note that we are unpacking the tuple argument into two separate instance variables.
        self.location_x = location[0]
        self.location_y = location[1]

# Create a new object "new_object_one", with object property (1, 2).
>>> new_object_one = MyClass((1, 2))

# Create a second new object "new_object_two" with object property (-8, -9).
>>> new_object_two = MyClass((-8, -9))

# Note that new_object_one.location_x and new_object_two.location_x two different values.
>>> new_object_one.location_x
1

>>> new_object_two.location_x
-8

মনে রাখবেন, উপরে MyClass ইনিশিয়ালাইজ করার সময় আপনাকে শুধু একটি আর্গুমেন্ট পাঠাতে হয়, কারণ ক্লাস কল করা হলে self পাঠানোর কাজ Python নিজেই সামলে নেয়।

Advanced

ইনস্ট্যান্স ভ্যারিয়েবল তৈরির আরেকটি উপায় হলো অবজেক্টের মাধ্যমে সরাসরি একটি ক্লাস ভ্যারিয়েবল ব্যবহার করে তার মান বদলে দেওয়া:

>>> obj_one = MyClass()
>>> obj_two = MyClass()
>>> MyClass.string
'Hello!'

>>> obj_two.string = "Hi!"
>>> obj_two.string
'Hi!'

>>> obj_one.string
'Hello!'

এখন দেখুন, ক্লাস ভ্যারিয়েবলের মান বদলালে কী হয়:

>>> MyClass.string = "World!"
>>> obj_two.string

# obj_two.string has not changed
'Hi!'

>>> obj_one.string

# obj_one.string changed
'World!'

obj_two-এর ক্ষেত্রে string অ্যাট্রিবিউটটি এখন একটি ইনস্ট্যান্স ভ্যারিয়েবল, কিন্তু obj_one-এ এটি ক্লাস ভ্যারিয়েবল হয়েই আছে।

ক্লাসের ভেতর থেকেও এটি করা যায়:

class Demo:
    new_var = 3

    def add_two(self):
        self.new_var += 2

<object>.add_two() কল হওয়ার সঙ্গে সঙ্গে এবং self.new_var += 2 পড়া হওয়ার মুহূর্তে, new_var ক্লাস ভ্যারিয়েবল থেকে একই নামের ইনস্ট্যান্স ভ্যারিয়েবলে পরিণত হয়।

ইনিশিয়ালাইজেশনের সময় এটি কাজে লাগতে পারে, যখন ক্লাসের সব ইনস্ট্যান্সের কিছু অ্যাট্রিবিউট একই মান দিয়ে শুরু করা দরকার হয়। তবে এরপর ইনস্ট্যান্স ভ্যারিয়েবলটি ক্লাস ভ্যারিয়েবলটিকে শ্যাডো করে, ফলে যে ইনস্ট্যান্সে শ্যাডো হয়েছে সেখান থেকে ক্লাস ভ্যারিয়েবলটি আর ব্যবহার করা যায় না। এই পরিস্থিতিতে __init__() মেথড থেকে self.<attribute> হিসেবে ইনস্ট্যান্স অ্যাট্রিবিউট সেট করাই হয়তো বেশি নিরাপদ ও স্পষ্ট।

মেথড

একটি method হলো এমন একটি function, যা ক্লাসের নিজের সাথে (যাকে ক্লাস মেথড বলা হয়, এবং পরে আরেকটি অনুশীলনীতে বিস্তারিত আলোচনা করা হবে) অথবা ক্লাসের একটি ইনস্ট্যান্স-এর (অবজেক্টের) সাথে বাঁধা থাকে। কোনো অবজেক্ট বা ইনস্ট্যান্সের উপর কাজ করে এমন মেথড ডিফাইন করতে প্রথম প্যারামিটার হিসেবে self দিতে হয়। এরপর বাকি প্যারামিটারগুলো একটি "সাধারণ" বা আনবাউন্ড ফাংশনের মতোই ডিফাইন করতে পারেন। ক্লাসের উপর কাজ করে এমন মেথড ডিফাইন করতে @classmethod ডেকোরেটর এবং (প্রথা অনুযায়ী) প্রথম প্যারামিটার হিসেবে cls দিতে হয়। ক্লাস মেথড ক্লাস থেকে প্রথমে কোনো অবজেক্ট না বানিয়েই সরাসরি কল করা যায়।

class MyClass:
    number = 5
    string = "Hello!"

    # Class constructor.
    def __init__(self, location):

        # Instance properties
        self.location_x = location[0]
        self.location_y = location[1]

    # Class method. Uses the @classmethod decorator, and cls as the first parameter.
    # Can be called without first making an instance of the class.
    @classmethod
    def change_string(cls, new_string):
        #Class attributes are referred to with cls.
        cls.string = new_string
        return cls.string

    # Instance method.  Note "self" as first parameter.
    def change_location(self, amount):
        self.location_x += amount
        self.location_y += amount
        return self.location_x, self.location_y

অ্যাট্রিবিউট ব্যবহারের মতোই, মেথড কল করাও ততটাই সহজ: অবজেক্টের নামের পরে এবং মেথডের নামের আগে একটি . বসিয়ে দিলেই হয়। কল করা মেথডের প্রথম প্যারামিটার হিসেবে অবজেক্টের কোনো কপি লাগে না, Python নিজে থেকেই self বসিয়ে দেয়:

class MyClass:
    number = 5
    string = "Hello!"

    def __init__(self, location):
        self.location_x = location[0]
        self.location_y = location[1]

    def change_location(self, amount):
        self.location_x += amount
        self.location_y += amount
        return self.location_x, self.location_y

# Make a new test_object with location (3,7)
>>> test_object = MyClass((3,7))
>>> (test_object.location_x, test_object.location_y)
(3,7)

# Call change_location to increase location_x and location_y by 7.
>>> test_object.change_location(7)
(10, 14)

ক্লাসের বাইরে যেভাবে ক্লাস অ্যাট্রিবিউট ব্যবহার করা হয়, ইনস্ট্যান্স মেথডের ভেতর থেকেও ঠিক সেভাবেই করা যায়:

class MyClass:
    number = 5
    string = "Hello!"

    def __init__(self, location):
        self.location_x = location[0]
        self.location_y = location[1]

    # Alter instance variable location_x and location_y
    def change_location(self, amount):
        self.location_x += amount
        self.location_y += amount
        return self.location_x, self.location_y

    # Alter class variable number for all instances from within an instance.
    def increment_number(self):
        # Increment the 'number' class variable by 1.
        MyClass.number += 1


>>> test_object_one = MyClass((0,0))
>>> test_object_one.number
5

>>> test_object_two = MyClass((13, -3))
>>> test_object_two.increment_number()
>>> test_object_one.number
6

pass দিয়ে প্লেসহোল্ডিং বা স্টাবিং ইমপ্লিমেন্টেশন

আগের কনসেপ্ট অনুশীলনী ও প্র্যাকটিস অনুশীলনীর স্টাবে আপনি ফাংশনের বডিতে আসল কোডের বদলে pass কিওয়ার্ড ব্যবহার হতে দেখেছেন।

pass কিওয়ার্ডটি সিনট্যাক্সের দিক থেকে বৈধ একটি প্লেসহোল্ডার, যা খালি ফাংশন বা ক্লাস ডেফিনিশনের জন্য Python-কে সিনট্যাক্স এরর দিতে বাধা দেয়। মূলত এটি Python ইন্টারপ্রেটারকে বলার একটি উপায়: 'চিন্তার কিছু নেই! আমি একসময় এখানে কোড লিখবই, এখনো লিখিনি শুধু।'

class MyClass:
    number = 5
    string = "Hello!"

    def __init__(self, location):
        self.location_x = location[0]
        self.location_y = location[1]

    # Alter instance variable location_x and location_y.
    def change_location(self, amount):
        self.location_x += amount
        self.location_y += amount
        return  self.location_x, self.location_y

    # Alter class variable number for all instances.
    def increment_number(self):
        # Increment the 'number' class variable by 1.
        MyClass.number += 1

    # This will compile and run without error, but has no current functionality.
    def pending_functionality(self):
       # Stubbing or place-holding the body of this method.
       pass
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে

ক্লাস শিখুন

অনুশীলন লক করা আছে

ক্লাস অনুশীলন করতে আরও 6টি অনুশীলনী আনলক করুন