سؤال

أنا أحاول أن أتعلم السوبر() وظيفة في بيثون.

اعتقدت أنني قد فهم من ذلك حتى لقد جاء على هذا المثال (2.6) وجدت نفسي عالقا.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in do_something
    do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>

لم يكن ما توقعته عندما قرأت هذا السطر من قبل على سبيل المثال:

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

وهو بالضبط ما بيثون يقول لي غير ممكن بالقول do_something() ينبغي أن يسمى مع مثيل B.

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

المحلول

في بعض الأحيان نصوص يجب أن تقرأ أكثر نكهة من الفكرة وليس على التفاصيل.هذا هو واحد من تلك الحالات.

في ربط الصفحة, أمثلة 2.5 و 2.6 و 2.7 يجب استخدام كل أسلوب واحد ، do_your_stuff.(وهذا هو ، do_something يجب تغيير do_your_stuff.)

وبالإضافة إلى ذلك ، نيد Deily أشار, A.do_your_stuff يجب أن يكون أسلوب فئة.

class A(object):
    @classmethod
    def do_your_stuff(cls):
        print 'This is A'

class B(A):
    @classmethod
    def do_your_stuff(cls):
        super(B, cls).do_your_stuff()

B.do_your_stuff()

super(B, cls).do_your_stuff ترجع لا بد طريقة (انظر الحاشية 2).منذ cls تم تمرير الوسيطة الثانية إلى super(), هو cls أن يحصل بد أن عاد الأسلوب.وبعبارة أخرى ، cls يحصل كما مر أول حجة طريقة do_your_stuff() من فئة A.

أن أكرر: super(B, cls).do_your_stuff() أسباب A's do_your_stuff طريقة ودعا مع cls مرت أول حجة.من أجل أن تعمل ، A's do_your_stuff يجب أن يكون أسلوب فئة.صفحة مرتبط لا يذكر ذلك ، ولكن هذا نهائيا في القضية.

PS. do_something = classmethod(do_something) هي الطريقة القديمة في صنع classmethod.الجديدة(إيه) طريقة هي استخدام @classmethod الديكور.


علما بأن super(B, cls) لا يمكن استبداله super(cls, cls).القيام بذلك يمكن أن يؤدي إلى حلقات لانهائية.على سبيل المثال ،

class A(object):
    @classmethod
    def do_your_stuff(cls):
        print('This is A')

class B(A):
    @classmethod
    def do_your_stuff(cls):
        print('This is B')
        # super(B, cls).do_your_stuff()  # CORRECT
        super(cls, cls).do_your_stuff()  # WRONG

class C(B):
    @classmethod
    def do_your_stuff(cls):
        print('This is C')
        # super(C, cls).do_your_stuff()  # CORRECT
        super(cls, cls).do_your_stuff()  # WRONG

C.do_your_stuff()

رفع RuntimeError: maximum recursion depth exceeded while calling a Python object.

إذا cls هو C, ثم super(cls, cls) البحث C.mro() للفئة التي تأتي بعد C.

In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]

منذ تلك الفئة B, عندما cls هو C, super(cls, cls).do_your_stuff() دائما المكالمات B.do_your_stuff.منذ super(cls, cls).do_your_stuff() ويسمى الداخل B.do_your_stuff, ، كنت في نهاية المطاف الدعوة B.do_your_stuff في حلقة لا نهائية.

في Python3 ، 0-حجة شكل super وأضيف لذلك super(B, cls) يمكن الاستعاضة عن super(), و Python3 سوف معرفة من السياق ، super() في تعريف class B يجب أن تكون أي ما يعادل super(B, cls).

ولكن في أي ظرف super(cls, cls) (أو لأسباب مماثلة ، super(type(self), self)) من أي وقت مضى الصحيح.

نصائح أخرى

في بيثون 3، يمكنك تخطي تحديد الحجج لsuper،

class A:
    @classmethod
    def f(cls):
        return "A's f was called."

class B(A):
    @classmethod
    def f(cls):
        return super().f()

assert B.f() == "A's f was called."

ولقد تحديث المادة لجعلها أكثر وضوحا قليلا: <لأ href = "http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#a-super-solution" يختلط = "نوفولو noreferrer "> بيثون سمات وطرق # سوبر

والمثال باستخدام classmethod أعلاه يظهر ما هو أسلوب فئة - يمر الفئة نفسها بدلا من المثال كمعلمة الأول. ولكنك لا تحتاج حتى مثيل استدعاء الأسلوب، لمنها مثلا:

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print cls
... 
>>> A.foo() # note this is called directly on the class
<class '__main__.A'>

والمثال من صفحة الويب يبدو للعمل كما نشرت. هل إنشاء أسلوب do_something لالفائقة كذلك، ولكن لا جعله classmethod؟ وشيء من هذا القبيل تعطيك هذا الخطأ:

>>> class A(object):
...     def do_something(cls):
...         print cls
... #   do_something = classmethod(do_something)
... 
>>> class B(A):
...     def do_something(cls):
...         super(B, cls).do_something()
...     do_something = classmethod(do_something)
... 
>>> B().do_something()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in do_something
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)

واعتقد انني فهمت النقطة الآن بفضل هذا الموقع الجميل والمجتمع جميل.

إذا كنت لا تمانع يرجى تصحيح لي إذا كنت مخطئا في classmethods (التي أحاول الآن أن نفهم تماما):


# EXAMPLE #1
>>> class A(object):
...     def foo(cls):
...             print cls
...     foo = classmethod(foo)
... 
>>> a = A()
>>> a.foo()
# THIS IS THE CLASS ITSELF (__class__)
class '__main__.A'

# EXAMPLE #2
# SAME AS ABOVE (With new @decorator)
>>> class A(object):
...     @classmethod
...     def foo(cls):
...             print cls
... 
>>> a = A()
>>> a.foo()
class '__main__.A'

# EXAMPLE #3
>>> class B(object):
...     def foo(self):
...             print self
... 
>>> b = B()
>>> b.foo()
# THIS IS THE INSTANCE WITH ADDRESS (self)
__main__.B object at 0xb747a8ec
>>>

وآمل أن يظهر هذا التوضيح ..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top