একাধিক উত্তরাধিকার সহ অভিভাবক শ্রেণি __init__ কল করা, সঠিক উপায় কি?


174

বলুন আমার একাধিক উত্তরাধিকারের পরিস্থিতি রয়েছে:

class A(object):
    # code for A here

class B(object):
    # code for B here

class C(A, B):
    def __init__(self):
        # What's the right code to write here to ensure 
        # A.__init__ and B.__init__ get called?

সেখানে লেখা দুটি টিপিক্যাল পন্থা নেই C'র __init__:

  1. (পুরাতন স্টাইল) ParentClass.__init__(self)
  2. (নতুন স্টাইলের) super(DerivedClass, self).__init__()

যাইহোক, উভয় ক্ষেত্রেই, যদি প্যারেন্ট ক্লাসগুলি ( Aএবং B) একই কনভেনশন অনুসরণ না করে, তবে কোডটি সঠিকভাবে কাজ করবে না (কিছুটি মিস হয়ে যেতে পারে, বা একাধিকবার কল হতে পারে)।

তাহলে আবার সঠিক উপায় কী? এটি বলা সহজ "কেবল সামঞ্জস্যপূর্ণ থাকুন, একজনকে বা অন্যটিকে অনুসরণ করুন", তবে যদি Aবা Bকোনও তৃতীয় পক্ষের লাইব্রেরি থেকে থাকেন তবে তা কি? এমন কোনও দৃষ্টিভঙ্গি রয়েছে যা নিশ্চিত করতে পারে যে সমস্ত অভিভাবক শ্রেণির নির্মাতাদের ডাকা হবে (এবং সঠিক ক্রমে এবং একবারে একবার)?

সম্পাদনা করুন: আমি কী বলতে চাইছি তা দেখার জন্য:

class A(object):
    def __init__(self):
        print("Entering A")
        super(A, self).__init__()
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        A.__init__(self)
        B.__init__(self)
        print("Leaving C")

তারপরে আমি পেয়েছি:

Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C

মনে রাখবেন যে Bএর আর দ্বিগুণ কল হয়েছিল। যদি আমি করি:

class A(object):
    def __init__(self):
        print("Entering A")
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        super(C, self).__init__()
        print("Leaving C")

তারপরে আমি পেয়েছি:

Entering C
Entering A
Leaving A
Leaving C

মনে রাখবেন যে Bএর আর কখনও কল হবে না। সুতরাং দেখে মনে হচ্ছে যে আমি যে ক্লাসগুলির ( আমার) উত্তরাধিকার সূত্রে জানতে পেরেছি সেগুলি সম্পর্কে জানতে / নিয়ন্ত্রণ না করা পর্যন্ত আমি ( Aএবং B) যে ক্লাসটি লিখছি তার জন্য নিরাপদ পছন্দ করতে পারি না C


উত্তর:


78

দুটি উপায়ই ঠিকঠাক কাজ করে। ব্যবহারের পদ্ধতিটি super()সাবক্লাসগুলির জন্য আরও নমনীয়তার দিকে পরিচালিত করে।

সরাসরি কল পদ্ধতির মধ্যে এবং C.__init__উভয়কে কল করতে পারেন ।A.__init__B.__init__

ব্যবহার করার সময় super(), ক্লাসগুলি সমবায় একাধিক উত্তরাধিকারের জন্য ডিজাইন করা দরকার যেখানে Cকলগুলি super, যা এর কোডকে Aআহ্বান করে superযা কোন কোডকে ডাকবে সেই কোডটিও ডাকবে B। কী কী করা যায় সে সম্পর্কে আরও তথ্যের জন্য http://rhettinger.wordpress.com/2011/05/26/super-considered-super দেখুন super

[পরবর্তী সময়ে সম্পাদিত হিসাবে প্রতিক্রিয়া প্রশ্ন]

সুতরাং দেখে মনে হচ্ছে যে আমি (এ এবং বি) উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাসগুলির ডিআইএসগুলি না জানি / নিয়ন্ত্রণ না করি আমি (C) লিখছি এমন শ্রেণীর জন্য নিরাপদ পছন্দ করতে পারি না।

রেফারেন্সযুক্ত নিবন্ধটি দেখায় যে কীভাবে এই পরিস্থিতিটি পরিচালনা করা যায় Aএবং প্রায় একটি মোড়কের ক্লাস যুক্ত করে B। "একটি অস-সহযোগী শ্রেণিকে কীভাবে অন্তর্ভুক্ত করা যায়" শিরোনামে বিভাগটিতে একটি পরিশ্রমের উদাহরণ রয়েছে।

কারও মনে হতে পারে যে একাধিক উত্তরাধিকার সহজ ছিল, ফ্লাইংকারটি পাওয়ার জন্য আপনাকে অনায়াসে গাড়ি এবং বিমানের ক্লাস রচনা করতে দিয়েছিল, তবে বাস্তবতাটি হ'ল পৃথকভাবে নকশাকৃত উপাদানগুলির জন্য প্রায়শই নির্বিঘ্নে একসাথে ফিট করার আগে আমাদের পছন্দ মতো অ্যাডাপ্টার বা মোড়কের প্রয়োজন হয় :-)

অন্য একটি ভাবনা: আপনি যদি একাধিক উত্তরাধিকার ব্যবহার করে রচনা কার্যকারিতা থেকে অসন্তুষ্ট হন তবে কোন পদ্ধতিতে কোন পদ্ধতিতে ডাকতে হবে তার উপর সম্পূর্ণ নিয়ন্ত্রণের জন্য আপনি রচনাটি ব্যবহার করতে পারেন।


4
না, তারা না। বি'র সূচনা যদি সুপারকে কল না করে, তবে আমরা যদি super().__init__()পদ্ধতির সাথে কাজ করি তবে বি এর আরআর কল করা হবে না । যদি আমি কল করি A.__init__()এবং B.__init__()সরাসরি, তবে (যদি A এবং B কল করে super) আমি বি এর আরআইপিটি একাধিকবার কল করা পেতে পারি ।
অ্যাডাম পার্কিন

3
@ অ্যাডামপারকিন (আপনার প্রশ্নটি সম্পাদিত হিসাবে সম্পর্কিত): প্যারেন্ট ক্লাসগুলির মধ্যে একটি সুপার () ব্যবহারের জন্য তৈরি করা হয়নি , তবে এটি সাধারণত এমনভাবে মোড়ানো যেতে পারে যাতে সুপার কল যুক্ত হয়। রেফারেন্স করা নিবন্ধটি "একটি অস-সহযোগী শ্রেণি কিভাবে সংযুক্ত করা যায়" শীর্ষক বিভাগে একটি পরিশ্রমের উদাহরণ দেখায়।
রেমন্ড হেটেঞ্জার

1
আমি যখন নিবন্ধটি পড়ি তখন কোনওভাবেই আমি সেই বিভাগটি মিস করতে পারি। ঠিক আমি যা খুঁজছিলাম ধন্যবাদ!
অ্যাডাম পার্কিন

1
আপনি যদি অজগর লিখছেন (আশা করি 3!) এবং যে কোনও ধরণের উত্তরাধিকার ব্যবহার করছেন তবে বিশেষত একাধিক, তবে rhettinger.wordpress.com/2011/05/26/super-considered-super পড়তে হবে।
শন মেহান

1
উত্সাহ দেওয়া কারণ আমরা অবশেষে জানি কেন আমাদের কাছে উড়ন্ত গাড়ি নেই কেন যখন আমরা নিশ্চিত হয়েছিলাম যে আমাদের এতক্ষণে হবে।
মিসৌথ

65

আপনার প্রশ্নের উত্তর একটি খুব গুরুত্বপূর্ণ দিকের উপর নির্ভর করে: আপনার বেস ক্লাসগুলি কি একাধিক উত্তরাধিকারের জন্য ডিজাইন করা হয়েছে?

এখানে 3 টি ভিন্ন পরিস্থিতিতে রয়েছে:

  1. বেস ক্লাসগুলি সম্পর্কিত নয়, স্বতন্ত্র ক্লাস।

    যদি আপনার বেস ক্লাসগুলি পৃথক সত্তা থাকে যা স্বতন্ত্রভাবে কাজ করতে সক্ষম হয় এবং তারা একে অপরকে চেনে না, তবে তারা একাধিক উত্তরাধিকারের জন্য ডিজাইন করা হয়নি । উদাহরণ:

    class Foo:
        def __init__(self):
            self.foo = 'foo'
    
    class Bar:
        def __init__(self, bar):
            self.bar = bar

    গুরুত্বপূর্ণ: লক্ষ করুন যে, তন্ন তন্ন Fooনা Barকল super().__init__()! এজন্য আপনার কোডটি সঠিকভাবে কাজ করে নি। কারণ উপায় পাইথন হীরা উত্তরাধিকার কাজ, ক্লাস যার বেস ক্লাস হয় objectকল করা উচিত নয়super().__init__() । আপনি লক্ষ্য করেছেন যে, এটি করার ফলে একাধিক উত্তরাধিকার ভেঙে যাবে কারণ আপনি অন্য ক্লাসের __init__পরিবর্তে কল করতে পারেন object.__init__()( বিশেষ দ্রষ্টব্য: এড়ানো super().__init__()মধ্যে object-subclasses আমার ব্যক্তিগত সুপারিশ এবং কোন মানে একটি স্বীকৃত উপর পাইথন কমিউনিটি ঐক্যমত্য কিছু মানুষ ব্যবহার করতে পছন্দ করেন। superযে arguing আপনি সর্বদাই একটি লিখতে পারেন, যে ক্লাসে অ্যাডাপ্টারের যদি শ্রেণী হিসেবে আচরণ করে না তুমি আশা কর.)

    এর অর্থ হ'ল আপনি কখনই এমন ক্লাস লিখবেন না যা উত্তরাধিকার সূত্রে প্রাপ্ত objectএবং যার কোনও __init__পদ্ধতি নেই। কোনও __init__পদ্ধতি নির্ধারণ না করা কল করার মতোই প্রভাব ফেলে super().__init__()। যদি আপনার শ্রেণি সরাসরি থেকে উত্তরাধিকার সূত্রে objectআসে তবে নিশ্চিত হয়ে নিন যে কোনও ফাঁকা নির্মাতা এটিকে যুক্ত করুন:

    class Base(object):
        def __init__(self):
            pass

    যাইহোক, এই পরিস্থিতিতে আপনাকে ম্যানুয়ালি প্রতিটি পিতামাতার কনস্ট্রাক্টরকে কল করতে হবে। এই কাজটি করার দুটি পদ্ধতি আছে:

    • ছাড়া super

      class FooBar(Foo, Bar):
          def __init__(self, bar='bar'):
              Foo.__init__(self)  # explicit calls without super
              Bar.__init__(self, bar)
    • সঙ্গে super

      class FooBar(Foo, Bar):
          def __init__(self, bar='bar'):
              super().__init__()  # this calls all constructors up to Foo
              super(Foo, self).__init__(bar)  # this calls all constructors after Foo up
                                              # to Bar

    এই দুটি পদ্ধতির প্রত্যেকটির নিজস্ব সুবিধা এবং অসুবিধা রয়েছে। আপনি যদি ব্যবহার করেন তবে superআপনার শ্রেণি নির্ভরতা ইনজেকশনটিকে সমর্থন করবে । অন্যদিকে, ভুল করা সহজ। উদাহরণস্বরূপ আপনি যদি Fooএবং Bar(যেমন class FooBar(Bar, Foo)) এর ক্রম পরিবর্তন করেন তবে আপনাকে মিলগুলি superকলগুলি আপডেট করতে হবে । superআপনি ছাড়া এই সম্পর্কে চিন্তা করতে হবে না, এবং কোডটি অনেক বেশি পঠনযোগ্য।

  2. ক্লাসগুলির একটি হ'ল মিক্সিন।

    একজন mixin একটি বর্গ যে হল পরিকল্পিত একাধিক উত্তরাধিকার সঙ্গে ব্যবহার করা। এর অর্থ হ'ল আমাদের উভয় প্যারেন্ট কনস্ট্রাক্টরকে ম্যানুয়ালি কল করতে হবে না, কারণ মিক্সিন স্বয়ংক্রিয়ভাবে আমাদের জন্য ২ য় কনস্ট্রাক্টরকে কল করবে। যেহেতু আমাদের কেবলমাত্র এবারই একটি একক কনস্ট্রাক্টরকে কল করতে হবে, তাই আমরা superপিতাম শ্রেণীর নামটি হার্ড-কোড না করে এড়াতে পারি ।

    উদাহরণ:

    class FooMixin:
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)  # forwards all unused arguments
            self.foo = 'foo'
    
    class Bar:
        def __init__(self, bar):
            self.bar = bar
    
    class FooBar(FooMixin, Bar):
        def __init__(self, bar='bar'):
            super().__init__(bar)  # a single call is enough to invoke
                                   # all parent constructors
    
            # NOTE: `FooMixin.__init__(self, bar)` would also work, but isn't
            # recommended because we don't want to hard-code the parent class.

    এখানে গুরুত্বপূর্ণ বিবরণগুলি হ'ল:

    • মিক্সিন কল করে super().__init__()এবং এটি প্রাপ্ত যে কোনও আর্গুমেন্টের মধ্য দিয়ে যায়।
    • Mixin থেকে উপশ্রেণী উত্তরাধিকারী প্রথম : class FooBar(FooMixin, Bar)। যদি বেস ক্লাসগুলির ক্রমটি ভুল হয় তবে মিক্সিনের কনস্ট্রাক্টর কখনই ডাকা হবে না।
  3. সমস্ত বেস ক্লাস সমবায় উত্তরাধিকার জন্য ডিজাইন করা হয়েছে।

    সমবায় উত্তরাধিকারের জন্য ডিজাইন করা ক্লাসগুলি অনেকটা মিক্সিনের মতো: তারা সমস্ত অব্যবহৃত তর্কগুলি পরবর্তী শ্রেণিতে পাস করে। আগের মত, আমাদের কেবল কল করতে হবে super().__init__()এবং সমস্ত প্যারেন্ট কন্সট্রাক্টর চেইন- কল হবে।

    উদাহরণ:

    class CoopFoo:
        def __init__(self, **kwargs):
            super().__init__(**kwargs)  # forwards all unused arguments
            self.foo = 'foo'
    
    class CoopBar:
        def __init__(self, bar, **kwargs):
            super().__init__(**kwargs)  # forwards all unused arguments
            self.bar = bar
    
    class CoopFooBar(CoopFoo, CoopBar):
        def __init__(self, bar='bar'):
            super().__init__(bar=bar)  # pass all arguments on as keyword
                                       # arguments to avoid problems with
                                       # positional arguments and the order
                                       # of the parent classes

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

    আমি পূর্বে উল্লিখিত নিয়মটিরও এটি ব্যতিক্রম। উভয়ই CoopFooএবং CoopBarউত্তরাধিকার সূত্রে প্রাপ্ত objectতবে তারা এখনও কল করে super().__init__()। যদি তারা তা না করে তবে কোনও সহযোগী উত্তরাধিকার থাকবে না।

নীচের লাইন: সঠিক বাস্তবায়ন আপনি যে শ্রেণীর কাছ থেকে উত্তরাধিকারী হয়েছেন তার উপর নির্ভর করে।

কনস্ট্রাক্টর একটি শ্রেণীর পাবলিক ইন্টারফেসের অংশ। ক্লাসটি যদি মিশ্রণ হিসাবে বা সমবায় উত্তরাধিকারের জন্য ডিজাইন করা হয় তবে তা অবশ্যই নথিভুক্ত করা উচিত। যদি দস্তাবেজগুলি ধরণের কিছু উল্লেখ না করে তবে এটি ধরে নেওয়া নিরাপদ যে শ্রেণিটি সমবায় একাধিক উত্তরাধিকারের জন্য নয়


2
তোমার দ্বিতীয় বিষয়টি আমাকে উড়িয়ে দিয়েছে। আমি কেবল কখনও মিশিনকে প্রকৃত সুপার বর্গের ডানদিকে দেখেছি এবং ভেবেছিলাম সেগুলি বেশ আলগা এবং বিপজ্জনক, যেহেতু আপনি পরীক্ষা করতে পারবেন না যে আপনি যে শ্রেণীর সাথে মিশ্রিত করছেন তার যে গুণাবলীর প্রত্যাশা রয়েছে তা আছে কিনা you আমি কোনও জেনারেলকে super().__init__(*args, **kwargs)মিশ্রণে লিখতে এবং প্রথমে এটি লেখার কথা ভাবি নি । এটা এত জ্ঞান করে তোলে।
মিনিক্স

10

হয় পদ্ধতির ("নতুন স্টাইল" বা "পুরাতন স্টাইল") কাজ করবে যদি আপনার Aএবং এর জন্য সোর্স কোডের নিয়ন্ত্রণ থাকেB । অন্যথায়, একটি অ্যাডাপ্টার শ্রেণীর ব্যবহারের প্রয়োজন হতে পারে।

উত্স কোড অ্যাক্সেসযোগ্য: "নতুন স্টাইল" এর সঠিক ব্যবহার

class A(object):
    def __init__(self):
        print("-> A")
        super(A, self).__init__()
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        super(B, self).__init__()
        print("<- B")

class C(A, B):
    def __init__(self):
        print("-> C")
        # Use super here, instead of explicit calls to __init__
        super(C, self).__init__()
        print("<- C")
>>> C()
-> C
-> A
-> B
<- B
<- A
<- C

এখানে, পদ্ধতির রেজোলিউশন অর্ডার (এমআরও) নিম্নলিখিত নির্দেশ দেয়:

  • C(A, B)dictates Aপ্রথম, তারপর B। এমআরও হ'ল C -> A -> B -> object
  • super(A, self).__init__()এমআরও শৃঙ্খলে চালু করা অবধি শুরু C.__init__হয় B.__init__
  • super(B, self).__init__()এমআরও শৃঙ্খলে চালু করা অবধি শুরু C.__init__হয় object.__init__

আপনি বলতে পারেন যে এই কেসটি একাধিক উত্তরাধিকারের জন্য ডিজাইন করা হয়েছে

উত্স কোড অ্যাক্সেসযোগ্য: "পুরানো শৈলী" এর সঠিক ব্যবহার

class A(object):
    def __init__(self):
        print("-> A")
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        # Don't use super here.
        print("<- B")

class C(A, B):
    def __init__(self):
        print("-> C")
        A.__init__(self)
        B.__init__(self)
        print("<- C")
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

এখানে, এমআরও কোনও বিষয় নয়, যেহেতু A.__init__এবং B.__init__স্পষ্টভাবে বলা হয়। class C(B, A):ঠিক পাশাপাশি কাজ করবে।

যদিও আগের কেসটি নতুন স্টাইলে একাধিক উত্তরাধিকারের জন্য এই কেসটি "ডিজাইন" করা হয়নি তবে একাধিক উত্তরাধিকার এখনও সম্ভব।


এখন, কি যদি Aএবং Bকোনো তৃতীয় পক্ষ লাইব্রেরি থেকে রয়েছে - অর্থাত, আপনার জন্য সোর্স কোড উপর কোন নিয়ন্ত্রণ আছে AএবংB ? সংক্ষিপ্ত উত্তর: আপনি একটি অ্যাডাপ্টার বর্গ যে কার্যকরী প্রয়োজনীয় ডিজাইন আবশ্যক superকল, তারপর ম্রো সংজ্ঞায়িত করতে একটি খালি বর্গ ব্যবহার (দেখুন উপর রেমন্ড Hettinger এর নিবন্ধsuper - বিশেষ করে অধ্যায়, "একটি অ সমবায় ক্লাস নিগমবদ্ধ কিভাবে")।

তৃতীয় পক্ষের পিতামাতা: Aবাস্তবায়ন করে না super; Bনা

class A(object):
    def __init__(self):
        print("-> A")
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        super(B, self).__init__()
        print("<- B")

class Adapter(object):
    def __init__(self):
        print("-> C")
        A.__init__(self)
        super(Adapter, self).__init__()
        print("<- C")

class C(Adapter, B):
    pass
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

শ্রেণি Adapterপ্রয়োগগুলি superযাতে Cএমআরও সংজ্ঞায়িত করতে পারে, যা super(Adapter, self).__init__()কার্যকর করা হলে কার্যকর হয়।

এবং যদি অন্যদিকে এটি হয়?

তৃতীয় পক্ষের পিতামাতা: Aপ্রয়োগ super; Bনা

class A(object):
    def __init__(self):
        print("-> A")
        super(A, self).__init__()
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        print("<- B")

class Adapter(object):
    def __init__(self):
        print("-> C")
        super(Adapter, self).__init__()
        B.__init__(self)
        print("<- C")

class C(Adapter, A):
    pass
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

মৃত্যুদন্ডের ক্রমটি স্যুইচ করা ছাড়া এখানে একই প্যাটার্ন Adapter.__init__; superপ্রথমে কল করুন, তারপরে স্পষ্ট কল করুন। লক্ষ্য করুন যে তৃতীয় পক্ষের পিতামাতার সাথে প্রতিটি ক্ষেত্রে একটি অনন্য অ্যাডাপ্টার শ্রেণি প্রয়োজন।

সুতরাং দেখে মনে হচ্ছে যে আমি যে ক্লাসগুলির ( আমার) উত্তরাধিকার সূত্রে জানতে পেরেছি সেগুলি সম্পর্কে জানতে / নিয়ন্ত্রণ না করা পর্যন্ত আমি ( Aএবং B) যে ক্লাসটি লিখছি তার জন্য নিরাপদ পছন্দ করতে পারি না C

যদিও আপনি ক্ষেত্রে যেখানে আপনি না সব ব্যবস্থা করতে সক্ষম নিয়ন্ত্রণ সোর্স কোড Aএবং Bএকটা এডাপটার বর্গ ব্যবহার করে, আপনার হবে যে সত্য জানে কিভাবে Init পিতা বা মাতা ক্লাস এর বাস্তবায়ন superতাই কাজ করার মধ্যে (যদি আদৌ)।


4

রেমন্ড তার উত্তরে যেমন বলেছিল, সরাসরি কল করার জন্য A.__init__এবং B.__init__ঠিকঠাক কাজ করে এবং আপনার কোডটি পঠনযোগ্য।

তবে এটি Cএবং সেই শ্রেণীর মধ্যে উত্তরাধিকারের লিঙ্কটি ব্যবহার করে না । সেই লিঙ্কটি অন্বেষণ করা আপনাকে আরও দৃistan়তা দেয় এবং পরিণতিতে রিফ্যাক্টরিংগুলি সহজতর করে এবং ত্রুটি-প্রবণ করে তোলে। কীভাবে এটি করা যায় তার একটি উদাহরণ:

class C(A, B):
    def __init__(self):
        print("entering c")
        for base_class in C.__bases__:  # (A, B)
             base_class.__init__(self)
        print("leaving c")

1
সেরা উত্তর imho। এটি আরও ভবিষ্যতের প্রতিরোধী হওয়ায় এটি বিশেষভাবে সহায়ক বলে মনে করেছে
স্টিফেন

3

এই নিবন্ধটি সমবায় একাধিক উত্তরাধিকার ব্যাখ্যা করতে সহায়তা করে:

http://www.artima.com/weblogs/viewpost.jsp?thread=281127

এটি দরকারী পদ্ধতির উল্লেখ করে mro()যা আপনাকে পদ্ধতির রেজোলিউশন ক্রম দেখায়। আপনার 2nd উদাহরণ, যেখানে আপনি কলে superমধ্যে A, superকল ম্রো উপর চলতে থাকে। ক্রমের পরবর্তী ক্লাসটি হ'ল B, Bএর কারণেই প্রথম বার বলা হয় init

অফিসিয়াল পাইথন সাইট থেকে আরও একটি প্রযুক্তিগত নিবন্ধ এখানে দেওয়া হয়েছে:

http://www.python.org/download/releases/2.3/mro/


2

আপনি যদি তৃতীয় পক্ষের লাইব্রেরি থেকে উপ-শ্রেণিবদ্ধ ক্লাসগুলি গুণান্বিত হন, তবে না, বেস ক্লাসের __init__পদ্ধতিগুলি (বা অন্য কোনও পদ্ধতি) কল করার ক্ষেত্রে কোনও অন্ধ দৃষ্টিভঙ্গি নেই যা বেস ক্লাসগুলি কীভাবে প্রোগ্রাম করা যায় তা নির্বিশেষে কার্যকরভাবে কাজ করে।

superজটিল একাধিক উত্তরাধিকার গাছের অংশ হিসাবে সমবায় পদ্ধতিতে পদ্ধতিগুলি বাস্তবায়নের জন্য নকশাকৃত ক্লাসগুলি লেখার পক্ষে এটি সম্ভব করে তোলে যা শ্রেণীর লেখকের জানা প্রয়োজন না। তবে এটি ব্যবহার করতে পারে বা না পারে স্বেচ্ছাচারী ক্লাস থেকে সঠিকভাবে উত্তরাধিকারী হওয়ার জন্য এটি ব্যবহার করার কোনও উপায় নেই super

মূলত, কোনও শ্রেণি নকশাকৃতভাবে উপ-শ্রেণিবদ্ধ করা হয়েছে superবা বেস ক্লাসে সরাসরি কল সহ ডিজাইন করা হয়েছে কিনা এমন একটি সম্পত্তি যা শ্রেণীর "পাবলিক ইন্টারফেস" এর অংশ, এবং এটি যেমন নথিভুক্ত করা উচিত। আপনি যদি লাইব্রেরির লেখক যেমনটি প্রত্যাশা করেন এবং লাইব্রেরিতে যুক্তিসঙ্গত ডকুমেন্টেশন থাকে তৃতীয় পক্ষের লাইব্রেরিগুলি ব্যবহার করেন তবে এটি সাধারণত আপনাকে নির্দিষ্ট জিনিস সাবক্লাস করার জন্য প্রয়োজনীয় কী তা বলে দেয়। যদি তা না হয় তবে আপনি যে শ্রেণীর সাব-ক্লাসিং করছেন সেগুলির উত্স কোডটি দেখতে হবে এবং তাদের বেস-শ্রেণি-অনুরোধ সম্মেলনটি কী তা দেখতে হবে। আপনি যদি এক বা একাধিক তৃতীয় পক্ষের লাইব্রেরি থেকে এমন একাধিক ক্লাস যুক্ত করে থাকেন যা গ্রন্থাগারের লেখকরা প্রত্যাশা করেন না , তবে ধারাবাহিকভাবে সুপার-ক্লাসের পদ্ধতিগুলি মোটেও অনুরোধ করা সম্ভব নয়; ক্লাস এ যদি ব্যবহার করে হায়ারার্কির অংশ হয় superএবং ক্লাস বি হায়ারার্কির অংশ যা সুপার ব্যবহার করে না, তবে কোনও বিকল্পই কাজ করার গ্যারান্টিযুক্ত নয়। আপনাকে একটি কৌশল নির্ধারণ করতে হবে যা প্রতিটি নির্দিষ্ট ক্ষেত্রে কাজ করার জন্য ঘটে।


@ রেমন্ড হিট্টিংগার ওয়েল, আপনি ইতিমধ্যে আপনার উত্তর সম্পর্কে কিছু চিন্তাভাবনা সহ একটি নিবন্ধ লিখেছেন এবং এর সাথে যুক্ত করেছেন, সুতরাং আমার মনে হয় না যে এতে আমার আরও যোগ হবে। :) আমি মনে করি না যে কোনও হাই-হায়ারার্কির সাথে কোনও অ-সুপার-ব্যবহারের ক্লাসটি সাধারণভাবে খাপ খাইয়ে নেওয়া সম্ভব; আপনাকে জড়িত নির্দিষ্ট শ্রেণীর জন্য উপযুক্ত সমাধান নিয়ে আসতে হবে।
বেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.