استدعاء طريقة الفصل الأصلي من الفصل الفرعي في بايثون؟

StackOverflow https://stackoverflow.com/questions/805066

سؤال

عند إنشاء تسلسل هرمي بسيط للكائنات في بايثون، أود أن أكون قادرًا على استدعاء أساليب الفئة الأصلية من فئة مشتقة.في بيرل وجافا، هناك كلمة رئيسية لهذا (super).في بيرل، قد أفعل هذا:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

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

في بايثون، يبدو أنه يجب علي تسمية الفئة الأصل بشكل صريح من الطفل.في المثال أعلاه، يجب أن أفعل شيئًا مثل Foo::frotz().

لا يبدو هذا صحيحًا، نظرًا لأن هذا السلوك يجعل من الصعب إنشاء تسلسلات هرمية عميقة.إذا كان الأطفال بحاجة إلى معرفة الفئة التي تحدد الطريقة الموروثة، فسيتم إنشاء جميع أنواع آلام المعلومات.

هل هذا قيد فعلي في لغة بايثون أم فجوة في فهمي أم كليهما؟

هل كانت مفيدة؟

المحلول

نعم، ولكن فقط مع جديد على غرار الطبقات . استخدم super() وظيفة:

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

لبيثون 3.x و يمكنك استخدام:

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

نصائح أخرى

لقد بيثون أيضا السوبر أيضا:

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

<اقتباس فقرة>   

وإرجاع الكائن الوكيل أن طريقة المندوبين يدعو إلى أحد الوالدين أو الأخوة فئة من نوع.   وهذا مفيد للوصول إلى الأساليب الموروثة التي تم تجاوز في فئة.   ترتيب البحث هو نفسه الذي يستخدمه getattr () إلا أن هذا النوع نفسه يتم تخطي.

مثال:

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()
ImmediateParentClass.frotz(self)

وسوف يكون على ما يرام، إذا كانت الفئة الأصل فورية محددة frotz نفسه أو ورثت ذلك. وهناك حاجة فقط super للحصول على الدعم المناسب ل<م> متعددة الميراث (وبعد ذلك يعمل فقط إذا كل فئة تستخدم بشكل صحيح). بشكل عام، AnyClass.whatever يذهب للبحث عن whatever في أسلاف AnyClass إذا AnyClass لا يعرف / تجاوز ذلك، وهذا ينطبق على "الطبقة طفل يدعو طريقة الأم"، كما لأية حادثة أخرى!

بايثون 3 لديه بناء جملة مختلف وأبسط لاستدعاء الطريقة الأصلية.

لو Foo الطبقة ترث من Bar, ، ثم من Bar.__init__ يمكن استدعاؤه من Foo عبر super().__init__():

class Foo(Bar):

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

ولقد أوضح العديد من الإجابات كيفية استدعاء أسلوب من الوالد الذي تجاوز في الطفل.

ولكن

<اقتباس فقرة>   

و"كيف يمكنك استدعاء الأسلوب فئة أصل من فئة الأطفال؟"

ويمكن أيضا أن يعني فقط:

<اقتباس فقرة>   

و"كيف تسمون الأساليب الموروثة؟"

ويمكنك استدعاء الأساليب الموروثة من الفئة الأصل تماما كما لو كانوا أساليب الفئة الطفل، ما دام لم يتم الكتابة فوقها.

ومنها مثلا. في بيثون 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"

نعم، وهذا قد يكون واضحا إلى حد ما، لكني أشعر أنه من دون ذلك مشيرا الناس قد ترك هذا الموضوع مع الانطباع عليك أن تقفز من خلال الأطواق سخيفة فقط للوصول إلى الأساليب الموروثة في بيثون. خاصة وأن هذه المعدلات مسألة غاية في عمليات البحث عن "كيفية الوصول إلى طريقة فئة أصل في بايثون"، وOP هو مكتوب من وجهة نظر شخص جديد إلى الثعبان.

ولقد وجدت: https://docs.python.org/3/tutorial/classes.html#inheritance أن تكون مفيدة في فهم كيف يمكنك الوصول إلى الأساليب الموروثة.

وهنا مثال استخدام على السوبر () : ل

#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

وهناك عظمى () في بيثون جدا. انها متزعزع قليلا، بسبب الطبقات old- ونمط جديد بيثون، ولكن هو شائع جدا تستخدم على سبيل المثال في منشئات:

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

وأود أن أوصي باستخدام 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()

إذا كنت لا تعرف كم من الحجج التي قد تحصل عليها، وتريد تمرير كل منهم حتى الطفل أيضا:

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

و(من: بيثون - أنظف وسيلة لتجاوز __init__ التي يكون فيها kwarg اختياري يجب أن تستخدم بعد السوبر () استدعاء )

وهناك عظمى () في بيثون أيضا.

مثال لكيفية يسمى أسلوب فئة السوبر من أسلوب فئة فرعية

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()) 

وهذا المثال هو مماثل لذلك الذي أوضح above.However هناك فارق واحد أن عظمى ليس لديها أي الحجج التي تم تمريرها إلى رمز أعلاه it.This هي القابلة للتنفيذ في بيثون 3.4 الإصدار.

في بايثون 2، لم يكن لدي الكثير من الحظ مع السوبر (). لقد استخدمت إجابة من jimifiki على هذا الموضوع SO كيفية الرجوع إلى طريقة الوالدين في بيثون ؟ . ثم، وأضاف لي تطور قليلا الخاصة به، والتي أعتقد أن وجود تحسن في قابلية الاستخدام (وخاصة إذا كان لديك أسماء فئة طويلة).

وتحديد الفئة الأساسية في وحدة واحدة:

 # 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()'

في هذا المثال، 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

class department:
    campus_name="attock"
    def printer(self):
        print(self.campus_name)

class CS_dept(department):
    def overr_CS(self):
        department.printer(self)
        print("i am child class1")

c=CS_dept()
c.overr_CS()
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()

وهذا هو أسلوب أكثر تجريدا:

super(self.__class__,self).baz(arg)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top