শিশু ক্লাস থেকে পিতামাতার ক্লাসের পদ্ধতিটি কল করবেন?


606

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

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}

পাইথনে, দেখা যাচ্ছে যে আমি সন্তানের কাছ থেকে স্পষ্টতই অভিভাবক শ্রেণির নাম রাখতে হবে। উপরের উদাহরণে, আমাকে এর মতো কিছু করতে হবে Foo::frotz()

এটি সঠিক বলে মনে হচ্ছে না কারণ এই আচরণটি গভীরভাবে শ্রেণিবিন্যাস করা শক্ত করে তোলে। যদি শিশুদের জানতে হয় কোন শ্রেণিটি উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিটি সংজ্ঞায়িত করে, তবে সমস্ত ধরণের তথ্য ব্যথা তৈরি হয়।

এটি কি পাইথনের প্রকৃত সীমাবদ্ধতা, আমার বোঝার ফাঁক বা উভয়ই?


3
আমি মনে করি অভিভাবক শ্রেণির নামকরণ কোনও খারাপ ধারণা নয়। যখন শিশু ক্লাসটি একাধিক পিতা-মাতার কাছ থেকে উত্তরাধিকার সূত্রে আসে তখন এটি সাহায্য করতে পারে, যেহেতু আপনি স্পষ্টতই অভিভাবক শ্রেণীর নাম রাখেন।

7
কোনও শ্রেণীর নামকরণের বিকল্পটি কোনও খারাপ ধারণা নয়, তবে বাধ্য হয়ে তা করা অবশ্যই হয়।
jhndodo

পাইথন 2 এবং পাইথন 3 https://www.python.org/dev/peps/pep-3135/ এর মধ্যে সুপার হ্যান্ডলিংয়ের পরিবর্তনগুলি সম্পর্কে সচেতন হন । শ্রেণীর নামকরণের প্রয়োজন নেই (যদিও এখনও aশ্বরের ধারণা হতে পারে, কমপক্ষে কখনও কখনও)।
jwpfox 21

উত্তর:


735

হ্যাঁ, তবে কেবল নতুন-স্টাইলের ক্লাস রয়েছেsuper()ফাংশনটি ব্যবহার করুন :

class Foo(Bar):
    def baz(self, arg):
        return super().baz(arg)

অজগর <3 এর জন্য, ব্যবহার করুন:

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)

53
আপনি কি "রিটার্ন বার.বাজ (স্ব, আরগ)" করতে পারবেন না? যদি তা হয় তবে এর থেকে ভাল আর কী হবে?

15
হ্যাঁ, আপনি পারেন, তবে ওপি কল সাইটটিতে সুপারক্লাসের নাম ছাড়াই এটি কীভাবে করবেন তা জিজ্ঞাসা করছিল (বার, এই ক্ষেত্রে)।
অ্যাডাম রোজেনফিল্ড

7
সুপার () একাধিক উত্তরাধিকারের সাথে অদ্ভুত। এটি "পরবর্তী" শ্রেণিতে কল করে। এটি প্যারেন্ট ক্লাস হতে পারে বা পুরোপুরি সম্পর্কিত নয় এমন শ্রেণি হতে পারে যা শ্রেণিবিন্যাসের অন্য কোথাও প্রদর্শিত হয়।
স্টিভ জেসোপ

6
আমি পাইথন ২.x ব্যবহার করি এবং আমি যখন এটি করি তখন আমি "ত্রুটি: অবশ্যই শ্রেণীবদ্ধ নয়, টাইপ হওয়া উচিত"
ক্রিস এফ

28
super(Foo, self)পাইথন ২.x এর বাক্য গঠন সঠিক? পাইথন 3.x এ, super()সঠিক পছন্দ করা হয়?
ট্রেভর বয়েড স্মিথ

143

পাইথনের পাশাপাশি রয়েছে সুপার :

super(type[, object-or-type])

এমন কোনও প্রক্সি অবজেক্ট ফেরত করুন যা পিতামাতাকে বা ভাইবোনের ধরণের শ্রেণিতে পদ্ধতি কল করে। এটি উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিগুলিতে অ্যাক্সেসের জন্য দরকারী যা কোনও শ্রেণিতে ওভাররাইড করা হয়েছে। সার্চ অর্ডারটি গেটআটার () দ্বারা ব্যবহৃত ঠিক একই ধরণের নিজেই এড়ানো যায়।

উদাহরণ:

class A(object):     # deriving from 'object' declares A as a 'new-style-class'
    def foo(self):
        print "foo"

class B(A):
    def foo(self):
        super(B, self).foo()   # calls 'A.foo()'

myB = B()
myB.foo()

7
অ্যাডামের চেয়ে ভাল উদাহরণ কারণ আপনি অবজেক্ট বেস ক্লাসের সাহায্যে একটি নতুন-স্টাইলের ক্লাস ব্যবহার করে দেখিয়েছেন। সবেমাত্র নতুন স্টাইলের ক্লাসগুলির লিঙ্কটি মিস করছি।
স্যামুয়েল

81
ImmediateParentClass.frotz(self)

তাত্ক্ষণিক অভিভাবক শ্রেণি frotzনিজেকে সংজ্ঞায়িত করেছে বা উত্তরাধিকার সূত্রে পেয়েছে তা ঠিক থাকবে। superকেবলমাত্র একাধিক উত্তরাধিকারের যথাযথ সমর্থনের জন্য প্রয়োজন (এবং তারপরে এটি কেবলমাত্র প্রতিটি শ্রেণি এটি সঠিকভাবে ব্যবহার করলে) কাজ করে। সাধারণভাবে, AnyClass.whateverসন্ধান যাচ্ছে whateverমধ্যে AnyClassএর পূর্বপুরুষ যদি AnyClassসংজ্ঞায়িত না / ওভাররাইড, এবং এই অন্য কোন সংঘটন জন্য হিসাবে "বাবা-মার পদ্ধতি কলিং শিশু শ্রেণী" জন্য কথা সত্য!


এটি আদেশ দেয় যে এই বিবৃতিটি কার্যকর করার জন্য ইমিডিয়েটপ্যারেন্টক্লাসও সুযোগে উপস্থিত থাকবে। মডিউল থেকে কেবল বস্তুটি আমদানি করা কোনও উপকারে আসবে না।
তুষার ওয়াজিরানী

যদি এটি একটি শ্রেণিবদ্ধ পদ্ধতি হয়?
শিপলু মোকাদ্দিম

@ তুষারবাজিরানী যদি অভিভাবক শ্রেণি তাত্ক্ষণিক parentহয় তবে তা পুরো শ্রেণীর আওতায় থাকে, তাই না?
ইয়ারোস্লাভ নিকিতেনকো

1
@ ইয়ারোস্লাভ নিকিটেনকো আমি ক্লাস নয়, একটি উদাহরণ আমদানির কথা বলছি।
তুষার ওয়াজিরানী

1
@ তুষারবাজিরানী এখন আমি বুঝতে পেরেছি, আপনাকে ধন্যবাদ। আমি বর্তমান শ্রেণীর পদ্ধতি থেকে কল করার বিষয়ে ভাবছিলাম (যেমনটি ওপি জানিয়েছে)।
ইয়ারোস্লাভ নিকিতেনকো

74

পাইথন 3 এর প্যারেন্ট পদ্ধতিতে কল করার জন্য একটি পৃথক এবং সহজ বাক্য গঠন রয়েছে।

যদি Fooশ্রেণি উত্তরাধিকার সূত্রে প্রাপ্ত হয় Barতবে তার মাধ্যমে Bar.__init__থেকে এর Fooমাধ্যমে প্রার্থনা করা যেতে পারে super().__init__():

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)

5
পাইথন শুনতে ভাল 3 এর আরও ভাল সমাধান রয়েছে। প্রশ্নটি পাইথন ২. এক্স থেকে এসেছে। যদিও পরামর্শ জন্য ধন্যবাদ।
jjohn

45

অনেক উত্তরে ব্যাখ্যা করা হয়েছে যে কীভাবে সন্তানের মধ্যে ওভাররাইড করা পিতামাতার কাছ থেকে একটি পদ্ধতি কল করা যায়।

যাহোক

"আপনি কীভাবে শিশু শ্রেণি থেকে পিতামাতার ক্লাসের পদ্ধতিটিকে কল করবেন?"

কেবল এটির অর্থও হতে পারে:

"আপনি উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিগুলি কীভাবে কল করবেন?"

আপনি অভিভাবক শ্রেণীর কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিগুলিকে কল করতে পারেন ঠিক যেমন তারা শিশু শ্রেণির পদ্ধতি ছিল, যতক্ষণ না সেগুলি ওভাররাইট করা হয়নি।

উদাহরণস্বরূপ পাইথন 3:

class A():
  def bar(self, string):
    print("Hi, I'm bar, inherited from A"+string)

class B(A):
  def baz(self):
    self.bar(" - called by baz in B")

B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"

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

আমি খুঁজে পেয়েছি: https://docs.python.org/3/tutorial/classes.html# উত্তরাধিকারসূত্রে আপনি উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিগুলিতে কীভাবে অ্যাক্সেস করবেন তা বোঝার জন্য দরকারী।


@ gizzmole কোন পরিস্থিতিতে এটি কাজ করে না? প্রাসঙ্গিক যে কোনও সতর্কতা বা সতর্কতা যুক্ত করতে পেরে আমি খুশি, তবে আপনি পোস্ট করা লিঙ্কটি এই উত্তরের সাথে কীভাবে প্রাসঙ্গিক ছিল তা আমি বুঝতে পারি না।
বেন

@ বেন দুঃখিত, আমি আপনার উত্তরটি যথেষ্ট যত্ন সহকারে পড়িনি। এই উত্তরটি কীভাবে ওভারলোড ফাংশন করবেন সে প্রশ্নের প্রশ্নের উত্তর দেয় না, তবে একটি পৃথক প্রশ্নের উত্তর দেয়। আমি আমার প্রাথমিক মন্তব্য মুছলাম।
gizzmole

@ জিজমোলে আহ, কোনও উদ্বেগ নেই। আমি বুঝতে পারি যে এই উত্তরটি ওভারলোডিং ফাংশনগুলিতে প্রযোজ্য নয়, তবে প্রশ্নটি স্পষ্টভাবে ওভারলোডিংয়ের উল্লেখ করে না (যদিও প্রদত্ত পার্ল উদাহরণটি ওভারলোডিংয়ের একটি ঘটনা দেখায়)। অন্যান্য উত্তরগুলির বেশিরভাগ অংশই ওভারলোডিংকে কভার করে - এটি এখানে যারা সেই ব্যক্তির জন্য এটির প্রয়োজন নেই।
বেন

@ যদি আমি বি () .বাজ () কে 'সি' নামের অন্য শ্রেণীর সি থেকে সংজ্ঞায়িত ওয়ার্স ব্যবহার করে কল করতে চাই তবে কী হবে? আমি সি (সি) ক্লাসে বি () .বাজ () করার চেষ্টা করেছি, যেখানে সেলফ স্ট্রিং অন্য ভল। মৃত্যুদন্ড কার্যকর করার সময় এটি আমাকে কিছুই দেয়নি
joey

@ জোয়ি আমি নিশ্চিত না আপনি কী করতে চাইছেন বা এটি যদি এই প্রশ্নের ক্ষেত্রের মধ্যে থাকে তবে। স্ট্রিং একটি স্থানীয় ভেরিয়েবল - সেটিং self.stringকিছুই করবে না। C শ্রেণিতে আপনি এখনও কল করতে পারেনB().bar(string)
বেন

26

এখানে সুপার () ব্যবহারের উদাহরণ রয়েছে :

#New-style classes inherit from object, or from another new-style class
class Dog(object):

    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self):
        self.moves.append('walk')
        self.moves.append('run')

    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super(Superdog, self).moves_setup()
        self.moves.append('fly')

dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly']. 
#As you can see our Superdog has all moves defined in the base Dog class

এটি কি খারাপ উদাহরণ নয়? আমি বিশ্বাস করি যে আপনার সম্পূর্ণ শ্রেণিবদ্ধ "নতুন স্টাইল" ক্লাস না করা এবং
সুপারকে

13

পাইথনেও একটি সুপার () রয়েছে। পাইথনের পুরাতন- এবং নতুন ধাঁচের ক্লাসগুলির কারণে এটি কিছুটা দুর্বল, তবে বেশিরভাগ ক্ষেত্রে যেমন ব্যবহারকারীর ক্ষেত্রে ব্যবহৃত হয়:

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5

9

আমি CLASS.__bases__ এই জাতীয় কিছু ব্যবহার করার পরামর্শ দেব

class A:
   def __init__(self):
        print "I am Class %s"%self.__class__.__name__
        for parentClass in self.__class__.__bases__:
              print "   I am inherited from:",parentClass.__name__
              #parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()

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

7

আপনি কতটা যুক্তি পেতে পারেন তা যদি না জানেন এবং সেগুলি সমস্ত সন্তানের কাছেও পাঠাতে চান:

class Foo(bar)
    def baz(self, arg, *args, **kwargs):
        # ... Do your thing
        return super(Foo, self).baz(arg, *args, **kwargs)

(থেকে: পাইথন - ওভাররাইড করার সবচেয়ে সহজ উপায় __init__ যেখানে সুপার () কলের পরে একটি alচ্ছিক কাওয়ার্গ অবশ্যই ব্যবহার করা উচিত? )


4

পাইথনেও সুপার () রয়েছে।

একটি উপ শ্রেণি পদ্ধতি থেকে কীভাবে সুপার ক্লাস পদ্ধতিটি ডাকা হয় তার উদাহরণ

class Dog(object):
    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self,x):
        self.moves.append('walk')
        self.moves.append('run')
        self.moves.append(x)
    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super().moves_setup("hello world")
        self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves()) 

এই উদাহরণটি উপরে বর্ণিত ব্যক্তির অনুরূপ ow তবে এর মধ্যে একটি পার্থক্য রয়েছে যে সুপারের কাছে কোনও যুক্তি নেই। উপরের কোডটি পাইথন ৩.৪ সংস্করণে কার্যকর করা যায়।


2

এই উদাহরণে cafec_paramএকটি বেস ক্লাস (পিতামাত্ত শ্রেণি) এবং abcএকটি শিশু শ্রেণি। বেস ক্লাসে পদ্ধতিটি abcকল করে AWC

class cafec_param:

    def __init__(self,precip,pe,awc,nmonths):

        self.precip = precip
        self.pe = pe
        self.awc = awc
        self.nmonths = nmonths

    def AWC(self):

        if self.awc<254:
            Ss = self.awc
            Su = 0
            self.Ss=Ss
        else:
            Ss = 254; Su = self.awc-254
            self.Ss=Ss + Su   
        AWC = Ss + Su
        return self.Ss


    def test(self):
        return self.Ss
        #return self.Ss*4

class abc(cafec_param):
    def rr(self):
        return self.AWC()


ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())

আউটপুট

56

56

56

1

পাইথন 2 এ, সুপার () এর সাথে আমার খুব ভাগ্য হয়নি। আমি এই এস থ্রেডটিতে জিমিফিকি থেকে উত্তরটি ব্যবহার করেছি কীভাবে পাইথনে পিতামাতার পদ্ধতিটি উল্লেখ করব? । তারপরে, আমি এটিতে আমার নিজের সামান্য বাঁকটি যুক্ত করেছি, যা আমি মনে করি ব্যবহারের উন্নতি (বিশেষত আপনার যদি দীর্ঘ শ্রেণীর নাম থাকে)।

একটি মডিউলে বেস ক্লাসটি সংজ্ঞায়িত করুন:

 # myA.py

class A():     
    def foo( self ):
        print "foo"

তারপরে ক্লাসটিকে অন্য মডিউলগুলিতে আমদানি করুন as parent:

# myB.py

from myA import A as parent

class B( parent ):
    def foo( self ):
        parent.foo( self )   # calls 'A.foo()'

2
তারপরে আপনাকে সুপার () ব্যবহারের class A(object): পরিবর্তে class A():কাজ করতে হবে
blndev

আমি নিশ্চিত না যে আমি অনুসরণ করি। আপনি ক্লাস সংজ্ঞা বলতে চান? স্পষ্টতই, আপনাকে কোনও ক্লাসের কোনও পিতা বা মাতা রয়েছে বলে মনে করতে হবে যাতে আপনি পিতামাতার সাথে উল্লেখ করতে পারেন! যেহেতু, আমি এটি 9 মাস আগে পোস্ট করেছি, আমি কিছুটা বিব্রত হয়েছি বিশদ, তবে আমি মনে করি যে আমি বলতে চাইছি অরুণ ঘোষের উদাহরণ, লরেন্স, কে কে কে, ইত্যাদি পাই ২.x এ প্রযোজ্য নয়। পরিবর্তে, এখানে একটি পদ্ধতি যা কাজ করে এবং পিতামাতার সাথে উল্লেখ করার একটি সহজ উপায় যাতে আপনি কী করছেন তা এটি আরও কিছুটা পরিষ্কার। (সুপার ব্যবহারের মতো)
বুভিনভিন


-4
class a(object):
    def my_hello(self):
        print "hello ravi"

class b(a):
    def my_hello(self):
    super(b,self).my_hello()
    print "hi"

obj = b()
obj.my_hello()

2
স্ট্যাকওভারফ্লোতে স্বাগতম। এই প্রশ্নের ইতিমধ্যে প্রায় দশ বছর আগে বিশদে উত্তর দেওয়া হয়েছে, উত্তরটি গৃহীত হয়েছে এবং মূলত upvated হয়েছে এবং আপনার উত্তরটি নতুন কিছু যোগ করে না। আপনি এর পরিবর্তে আরও সাম্প্রতিক (এবং অগ্রাধিকারযুক্ত উত্তর না দেওয়া) প্রশ্নের উত্তর চাইতে পারেন। পার্শ্ব নোট হিসাবে, সঠিক কোড ফর্ম্যাটিং প্রয়োগ করার জন্য সম্পাদকের একটি বোতাম রয়েছে।
ব্রুনো desthuilliers

-24

এটি আরও বিমূর্ত পদ্ধতি:

super(self.__class__,self).baz(arg)

15
স্ব .__ class__ অধিকার সুপার সাথে কাজ করে না স্ব সবসময় উদাহরণস্বরূপ এবং তার যেমন বর্গ সবসময় উদাহরণস্বরূপ এর বর্গ। এর অর্থ যদি আপনি একটি ক্লাসে সুপার (স্ব .__ শ্রেণি__ ..) ব্যবহার করেন এবং সেই শ্রেণিটি উত্তরাধিকার সূত্রে প্রাপ্ত হয় তবে এটি আর কাজ করবে না
xitrium

16
কেবল জোর দেওয়ার জন্য, এই কোডটি ব্যবহার করবেন না। এটি সুপার () এর পুরো উদ্দেশ্যকে পরাস্ত করে, যা সঠিকভাবে এমআরওকে অতিক্রম করে।
ইভি

1
stackoverflow.com/a/19257335/419348 বলেন কেন কল না super(self.__class__, self).baz(arg)
এচলোলিউ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.