Python super () TypeError'ı yükseltir


109

Python 2.5'te, aşağıdaki kod a'yı yükseltir TypeError:

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

Ben değiştirirseniz class Xile class X(object), işe yarayacak. Bunun açıklaması nedir?


3
"ancak X sınıfını X sınıfıyla (nesne) değiştiririm" sorunumu çözdü! thanx
AliBZ

Yanıtlar:


132

Bunun nedeni, super()yalnızca 2.x serisinde şunlardan genişleme anlamına gelen yeni stil sınıflarında çalışmasıdırobject :

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b

4
Bu hangi python sürümünden varsayılan davranış haline geldi?
Geo

6
2.2, yeni stil sınıflarının tanıtıldığı zamandı, 3.0, varsayılan oldukları yerdi.
Cody Brocious

7
@tsunami, süper sınıfa girmek istiyorsan "Xa (kendi kendine)" yap
James Brady

Sanırım beni yanlış anladın . Triptych. 3.0'dan daha düşük bir python sürümü kullandığımı hatırlıyorum ve özellikle sınıfımın Object'ten miras aldığını ve süper çağrısının çalıştığını söylemedim. Belki 2.6'daki varsayılan davranıştır? Sadece :)
Geo

Alabaster, buna gerçekten gerek yok. Yeni stil sınıflarının sadece süper değil, çok sayıda avantajı vardır. Eski tarz yollar tanıtılmamalıdır.
Cody Brocious

14

Ayrıca, mecbur kalmadıkça super () kullanmayın. Şüphelenebileceğiniz yeni tarz sınıflarla yapılacak genel amaçlı "doğru şey" değildir.

Birden fazla miras beklediğiniz zamanlar vardır ve muhtemelen bunu isteyebilirsiniz, ancak MRO'nun tüylü ayrıntılarını öğrenene kadar, en iyisi onu yalnız bırakın ve şunlara bağlı kalın:

 X.a(self)

2
bu doğru mu çünkü 6 aylık Python / Django'da "yapılacak genel doğru şey" olarak süper kullanıyorum?
philgo20

1
Tek başına kalıtım için size zarar vermez (biraz daha yavaş olması dışında), ama kendi başına da size hiçbir şey vermez. Açık __init__ve mantıklı bir şekilde argümanlardan geçmek için çoğaltma-miras alma (en önemlisi ) gereken herhangi bir yöntemi tasarlamanız gerekir , aksi takdirde birisi sınıfınızı kullanarak çoğaltma-miras almaya çalıştığında TypeErrors veya daha kötü hata ayıklama sorunları alırsınız. MI'yı gerçekten bu şekilde desteklemek için tasarlamadıysanız (ki bu oldukça zordur), superyöntemin MI güvenli olduğu sonucuna varmaktan kaçınmak muhtemelen daha iyidir .
bobince

3

Yukarıdaki cevaplardan hiçbirinin açıkça belirtmemesi durumunda. Ana sınıfınızın "nesneden" miras alması gerekir, bu da onu esasen yeni bir stil sınıfına dönüştürür.

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass

Üzgünüz, ancak Python 3.x'te ikinci örneğiniz (örtük kalıtım) bahsedilen sorun bağlamında gerçekten çalışmıyor.
sophros

1

Çeşitli Xa () yöntemlerini denedim; ancak, a () gerçekleştirmek için bir X örneğine ihtiyaç duyuyor gibi görünüyorlar, bu yüzden X (). Gereksiz inşaat ve yıkım olduğu için sorunu çözmenin iyi bir yolu gibi görünmüyor, ancak iyi çalışıyor.

Benim özel uygulamam Python'un cmd.Cmd modülüydü, bu belli bir sebepten dolayı NewStyle nesnesi değil.

Son sonuç:

X().a(self)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.