পাইথনে মাল্টিপল ইনহ্যারিটেন্স যেভাবে কাজ করে

বেশির ভাগ প্রোগ্রামারই মাল্টিপল ইনহ্যারিটেন্স ব্যাবহার করতে নিষেধ করেন। তারপরও বিশেষ কিছু ক্ষেত্রে আমাদের মাল্টিপল ইনহ্যারিটেন্স ব্যাবহার করতে হয়। তাহলে জেনে নেয়া যাক পাইথনে মাল্টিপল ইনহ্যারিটেন্স যে অর্ডার অনুসারে কাজ করে।

নিচের ডায়াগ্রাম টি দেখি:

পাইথনে মাল্টিপল ইনহ্যারিটেন্স

এই ডায়াগ্রাম অনুযায়ী কোড লিখি তাহলে:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class A(object):
    def test(self):
        print("Test from A")


class B(object):
    def test(self):
        print("Test from B")


class C(A, B):
    pass


c_instance = C()
c_instance.test()

এখন আমরা যদি কোডটি রান করি তাহলে আউটপুট কী আসবে?

কোডটির আউটপুট আসবে:

Test from A

অর্থাৎ আমরা যখন c_instance এর উপর test() মেথডটি কল করলাম, পাইথন প্রথমে এ মেথড টিকে C ক্লাসে খুজেছে। না পেয়ে এরপর A ক্লাসে খুজেছে। এখানে পেয়ে গেছে। এখানেও না পেলে তখন B ক্লাসে খুঁজত।

এই যে খোঁজাখুজি, পাইথন কোনটার পর কোনটায় খুঁজবে – এ ব্যাপারটিকে বলে মেথড রেজ্যুলেশন অর্ডার। আমরা যদি C ক্লাস এর মেথড রেজুলেশন অর্ডার দেখতে চাই, তাহলে যা করতে হবে:

17
print(C.mro())

তাহলে এরকম আউটপুট পাবো:

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

আচ্ছা এখন তাহলে এ ডায়াগ্রামটি দেখি:

পাইথনে মাল্টিপল ইনহ্যারিটেন্স

এখন এই ডায়াগ্রাম অনুযায়ী কোড লিখি:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class A(object):
    def test(self):
        print("Test from A")


class B(A):
    pass


class C(object):
    def test(self):
        print("Test from C")


class D(B, C):
    pass


d_instance = D()
d_instance.test()

তাহলে এ কোডের আউটপুট কি হবে?

কোডের আউটপুট হবে এরকম:

Test from A

কি! উল্টাপাল্টা মনে হচ্ছে?

আসলে পাইথনে মেথড রেজ্যুলেশন অর্ডার ডেপথ-ফার্স্ট সার্চিং উপায়ে কাজ করে। ডেপথ-ফার্স্ট অনুযায়ী তাহলে অর্ডার হবে এমন: D -> B -> A -> C। তাই আমাদের আউটপুট এমন এসেছে।

আরেকটু নিশ্চিত হই:

21
print(D.mro())

এটার আউটপুট আসবে এরকম:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]

আচ্ছা, তাহলে সব ঠিক ঠাকই আছে। কিন্তু মাল্টিপল ইনহ্যারিটেন্স যদি নিচের ডায়াগ্রামের মত হয় তাহলে!

পাইথনে মাল্টিপল ইনহ্যারিটেন্স ডায়মন্ড শেপ

এই ডায়াগ্রাম অনুযায়ী কোড:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class A(object):
    def test(self):
        print("Test from A")


class B(A):
    pass


class C(A):
    def test(self):
        print("Test from C")


class D(B, C):
    pass


d_instance = D()
d_instance.test()

এই কোডের আউটপুট কী হব?

আউটপুট জানার আগে D ক্লাসের মেথড রেজ্যুলেশন অর্ডার বের করার চেষ্টা করি। ডেপথ-ফার্স্ট অনুযায়ী মেথড রেজ্যুলেশন অর্ডার এরকম হবার কথা: D -> B -> A -> C -> A

তাহলে আউটপুট আসার কথা:

Test from A

এখন কোডটি রান করে দেখি কী আউটপুট আসে:

Test from C

আহা! এরকম আউটপুট আসল কী করে! মেথড রেজ্যুলেশন অর্ডার চেক করে দেখি তো:

21
print(D.mro())

আউটপুট:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

অর্থাৎ D -> B -> C -> A। তাহলে এটা ডেপথ-ফার্স্ট হলো কী করে!

পাইথন 2.3 থেকে নতুন একটি রুল যুক্ত হয়েছে। মেথড রেজ্যুলেশন অর্ডারের ডেপথ-ফার্স্টে যদি একই উপাদান একাধিক বার আসে, তাহলে একেবারে শেষটি রেখে বাকি গুলো মুছে দেয়া হয়। এখানে A দুইবার এসেছিল। তাই শুধু শেষেটি রাখা হয়েছে।

আশা করি ব্যাপারটি এখন পরিষ্কার হয়েছে। পোস্টটি ভাল লাগলে কমেন্ট করুন আর বন্ধুদের সাথে শেয়ার করুন। আর যদি কোন ভুল ত্রুটি খুঁজে পান, তাহলেও কমেন্টের মধ্যমে জানান। দ্রুত আপডেট করা হবে ইনশা-আল্লাহ।

Load Comments?