باستخدام السوبر مع أسلوب فئة
-
08-07-2019 - |
سؤال
أنا أحاول أن أتعلم السوبر() وظيفة في بيثون.
اعتقدت أنني قد فهم من ذلك حتى لقد جاء على هذا المثال (2.6) وجدت نفسي عالقا.
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
>>>
وآمل أن يظهر هذا التوضيح ..