সুপার ব্যবহার করার সঠিক উপায় (যুক্তি পাসিং)


105

তাই আমি পাইথনের সুপার বিবেচিত ক্ষতিকারককে অনুসরণ করছিলাম এবং তার উদাহরণগুলি পরীক্ষা করতে গিয়েছিলাম।

তবে উদাহরণ ১-২ , যা বিভিন্ন যুক্তি প্রত্যাশা করে এমন পদ্ধতিগুলি superপরিচালনা __init__করার সময় কল করার সঠিক উপায়টি দেখানোর কথা বলে মনে হয় , ফ্ল্যাট আউট কাজ করে না।

এটি আমি পেয়েছি:

~ $ python example1-3.py 
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
  File "Download/example1-3.py", line 27, in <module>
    E(arg=10)
  File "Download/example1-3.py", line 24, in __init__
    super(E, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 14, in __init__
    super(C, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 4, in __init__
    super(A, self).__init__(*args, **kwargs)
  File "Download/example1-3.py", line 19, in __init__
    super(D, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 9, in __init__
    super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters

দেখে মনে হয় যে objectডকুমেন্টে উল্লিখিত সেরা অনুশীলনের মধ্যে এটি নিজে লঙ্ঘন করেছে, এটি হ'ল যে পদ্ধতিগুলি ব্যবহার করে superঅবশ্যই তা গ্রহণ করতে হবে *argsএবং **kwargs

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

তাহলে এই সমস্যাটি মোকাবেলার সঠিক উপায় কী?


4
আমার পছন্দের উপায় হ'ল: সমতল এবং সাধারণ উত্তরাধিকারের স্তরক্রম।
মিলিমুজে

20
ভারসাম্যপূর্ণ দৃষ্টিভঙ্গি পাওয়ার জন্য আপনার "পাইথনের সুপার () সুপার হিসাবে বিবেচিত" পড়তে হবে :)
বিজন পোলাক্স

@ বিজেআরএনপ্লেক্স: ধন্যবাদ! আপনার লিঙ্ক প্রশ্নের উত্তর প্রদান করে: আপনি একটি "মূল শ্রেণী" যা থেকে উত্তরাধিকারী লিখতে পারেন object, এবং এটি কলে নিশ্চিত করে তোলে object's __init__সঠিকভাবে।
cha0site

4
দ্রষ্টব্য যে পাইথন 2.5 __init__তে objectনীরবে কোনও পরামিতি উপেক্ষা করে। এটি পাইথন ২.6 এ পরিবর্তিত হয়েছে।
উইলফ্রেড হিউজেস

4
@ উইলফ্রেড: আরে, আসল প্রশ্নের উত্তর দেওয়ার জন্য ধন্যবাদ! এখন আমি জানি যে প্রবন্ধটি সেকেলে কেন!
cha0site

উত্তর:


111

কখনও কখনও দুটি ক্লাসে কিছু প্যারামিটারের নাম থাকতে পারে। সেক্ষেত্রে আপনি কী-মান জোড়গুলি পপ করতে **kwargsবা এগুলি থেকে সরাতে পারবেন না *args। পরিবর্তে, আপনি কোনও Baseশ্রেণি সংজ্ঞায়িত করতে পারেন যা objectআর্গুমেন্টের বিপরীতে , শোষণ / উপেক্ষা করে:

class Base(object):
    def __init__(self, *args, **kwargs): pass

class A(Base):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(Base):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(arg, *args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(arg, *args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(arg, *args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10)

উৎপাদনের

MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B

মনে রাখবেন যে এটি কাজ করার জন্য, Baseঅবশ্যই এমআরওয়ের পেনাল্টিমেট শ্রেণি হবে।


4
Baseকল করা উচিত নয় super(Base, self).__init__()?
cha0site

4
এটি কাজ করার জন্য Baseঅবশ্যই এমআরও এর শেষে আসতে হবে (ব্যতীত object)। কলিং object.__init__কিছুই করে না, তাই কল করা ঠিক না super(Base, self).__init__()। প্রকৃতপক্ষে, আমি মনে করি super(Base, self).__init__()যে Baseলাইনের শেষ অংশটি বাড়িতে চালানো অন্তর্ভুক্ত না করা আরও পরিষ্কার হতে পারে ।
আনটবু

27

যদি আপনি অনেক উত্তরাধিকার পেতে চলেছেন (তবে এটিই এখানে) আমি আপনাকে সমস্ত পরামিতি ব্যবহার করে পাস করার পরামর্শ দিই **kwargs, এবং তারপরে popআপনি তাদের ব্যবহার করার পরেও (যদি না আপনার উচ্চ শ্রেণীর ক্ষেত্রে প্রয়োজন হয়)।

class First(object):
    def __init__(self, *args, **kwargs):
        self.first_arg = kwargs.pop('first_arg')
        super(First, self).__init__(*args, **kwargs)

class Second(First):
    def __init__(self, *args, **kwargs):
        self.second_arg = kwargs.pop('second_arg')
        super(Second, self).__init__(*args, **kwargs)

class Third(Second):
    def __init__(self, *args, **kwargs):
        self.third_arg = kwargs.pop('third_arg')
        super(Third, self).__init__(*args, **kwargs)

এই ধরণের সমস্যা সমাধানের সহজ উপায়।

third = Third(first_arg=1, second_arg=2, third_arg=3)

7

পাইথনের সুপার () সুপার হিসাবে বিবেচিত হয়েছে , এর একটি উপায় হ'ল ক্লাসে প্রয়োজনীয় আর্গুমেন্ট খাওয়া এবং বাকী অংশটি পাস করা। সুতরাং, কল-চেইন পৌঁছে গেলে objectসমস্ত যুক্তি খাওয়া হয়ে গেছে এবং object.__init__তর্ক ছাড়াই ডাকা হবে (যেমনটি এটি প্রত্যাশা করে)। সুতরাং আপনার কোডটি দেখতে এমন হওয়া উচিত:

class A(object):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(object):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(*args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(*args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(*args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10, 20, 30)

তো, কী E(arg = 10)? আমি এই পদ্ধতিটি পছন্দ করি না, এটি ব্যবহারের জন্য আমার আগেই এমআরও জানতে হবে। অন্য যে পদ্ধতিতে আমি "রুট শ্রেণি" লিখি যা উত্তরাধিকার সূত্রে প্রাপ্ত তা objectঅনেক পরিষ্কার মনে হয়।
CH0site

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