Temel (süper) sınıfı nasıl başlatırım?


126

Python'da, aşağıdaki koda sahip olduğumu düşünün:

>>> class SuperClass(object):
    def __init__(self, x):
        self.x = x

>>> class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

SuperClass __init__Alt sınıfta nasıl başlatırım ? Python öğreticisini takip ediyorum ve bunu kapsamıyor. Google'da arama yaptığımda, yapmanın birden fazla yolunu buldum. Bunu halletmenin standart yolu nedir?

Yanıtlar:


147

Python (sürüm 3'e kadar) "eski stil" ve yeni stil sınıflarını destekler. Yeni stil sınıfları, objectkullandığınız şeyden türetilir ve bunlardır ve temel sınıflarını super()örn.

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Python eski ve yeni tarz sınıfları bildiğinden, temel yöntemi çağırmanın farklı yolları vardır, bu yüzden bunu yapmanın birden çok yolunu buldunuz.

Bütünlük uğruna, eski tarz sınıflar temel sınıfları açıkça kullanarak temel yöntemleri çağırır, yani

def doit(self, foo):
  return X.doit(self, foo)

Ama artık eski tarzı kullanmaman gerektiğine göre, bunu fazla önemsemem.

Python 3 yalnızca yeni stil sınıfları bilir (türetip türetmediğiniz önemli objectdeğil).


38

Her ikisi de

SuperClass.__init__(self, x)

veya

super(SubClass,self).__init__( x )

çalışacaktır (KURU ilkesine daha çok bağlı olduğu için 2. olanı tercih ederim).

Buraya bakın: http://docs.python.org/reference/datamodel.html#basic-customization


8
yanlış. super, yalnızca yeni stil sınıflarla çalışır ve yeni stil sınıfları kullanırken bir üs çağırmanın tek uygun yoludur. Ayrıca, eski tarz yapıyı kullanarak 'self'i açıkça aktarmanız gerekir.
Ivo van der Wijk

1
@Ivo - OP, örnekte yeni bir stil sınıfı verdi ve artık hiç kimse eski stili kullanmaması gerektiğinden yeni stil ile eski stil arasındaki fark hakkında konuşmanın pek bir anlamı yok. Verdiğim bağlantı (Python belgelerine), süper sınıfı çağırmanın birden fazla "uygun" yolu olduğunu gösteriyor __init__.
adamk


21

Temel (süper) sınıfı nasıl başlatırım?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

superYöntem çözümleme sırasında sonraki yöntemi (bağlı yöntem olarak) aldığınızdan emin olmak için bir nesne kullanın . Python 2'de, selfbağlı __init__yöntemi aramak için sınıf adını iletmeniz ve süper yapmanız gerekir :

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

Python 3'te, argümanları supergereksiz kılan küçük bir sihir var - ve bir yan fayda olarak biraz daha hızlı çalışıyor:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

Ebeveyni aşağıdaki gibi sabit kodlamak, işbirlikçi çoklu kalıtımı kullanmanızı engeller:

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

__init__Yalnızca geri dönebileceğiniNone unutmayın - nesneyi yerinde değiştirmek için tasarlanmıştır.

bir şey __new__

Örnekleri başlatmanın başka bir yolu var - ve Python'daki değişmez türlerin alt sınıfları için tek yol bu. Eğer alt sınıfa istiyorsanız gerekli olduğunu strveya tupleveya başka değişmez bir nesne.

Örtük bir sınıf argümanı aldığı için bunun bir sınıf yöntemi olduğunu düşünebilirsiniz. Ama aslında statik bir yöntem . Yani çağırmanız gerekir __new__ile clsaçıkça.

Örneği genellikle adresinden döndürürüz __new__, bu yüzden eğer yaparsanız, __new__üssünüzün superyanı sıra temel sınıfınızda da aramanız gerekir . Yani her iki yöntemi de kullanırsanız:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3 __new__, statik bir yöntem olmasının neden olduğu süper çağrıların tuhaflığından biraz kaçıyor , ancak yine de clsbağlı olmayan __new__yönteme geçmeniz gerekiyor :

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')
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.