Bir super()
ebeveynin bir classmethod, instance yöntemi veya staticmethod sürümüne çözüm bulmak için çağrı yaparken , hangi argümanın kapsamını çözmeye çalıştığımızı belirtmek için, kapsamı ilk argüman olarak içinde bulunduğumuz geçerli sınıfı geçmek istiyoruz. ilgi konusu nesneyi, o kapsamı uygulamaya çalıştığımızı gösteren ikinci bir argüman.
Düşünün bir sınıf hiyerarşisi A
, B
ve C
her sınıf onu takip eden üstüdür ve burada a
, b
ve c
her birinin ayrı ayrı örneklerini.
super(B, b)
# resolves to the scope of B's parent i.e. A
# and applies that scope to b, as if b was an instance of A
super(C, c)
# resolves to the scope of C's parent i.e. B
# and applies that scope to c
super(B, c)
# resolves to the scope of B's parent i.e. A
# and applies that scope to c
super
Statik yöntemle kullanma
örneğin yöntem super()
içinden kullanma__new__()
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return super(A, cls).__new__(cls, *a, **kw)
Açıklama:
1- __new__()
ilk param olarak çağıran sınıfa başvuru yapmak olağan olsa da , Python'da bir sınıf yöntemi olarak değil , bir statik yöntem olarak uygulanmaktadır. Yani, __new__()
doğrudan çağırırken bir sınıfa yapılan başvurunun ilk argüman olarak açıkça iletilmesi gerekir :
# if you defined this
class A(object):
def __new__(cls):
pass
# calling this would raise a TypeError due to the missing argument
A.__new__()
# whereas this would be fine
A.__new__(A)
2- super()
Ana sınıfa ulaşmak için çağrıldığında A
, ilk argüman olarak alt sınıftan geçiyoruz, sonra ilgilenilen nesneye bir referans geçiyoruz, bu durumda A.__new__(cls)
çağrıldığında geçirilen sınıf referansı . Çoğu durumda, alt sınıfa da bir referans olur. Bazı durumlarda, örneğin çoklu nesil miraslar söz konusu olmayabilir.
super(A, cls)
3- Genel bir kural __new__()
olarak bir statik yöntem olduğu için, super(A, cls).__new__
aynı zamanda bir statik yöntem de döndürür ve bu durumda içsel nesneye yapılan başvuru da dahil olmak üzere tüm argümanların açıkça sağlanması gerekir cls
.
super(A, cls).__new__(cls, *a, **kw)
4- Aynı şeyi olmadan yapmak super
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return object.__new__(cls, *a, **kw)
super
Örnek yöntemiyle kullanma
örneğin super()
içeriden kullanmak__init__()
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
super(A, self).__init__(*a, **kw)
Açıklama:
1- __init__
bir örnek yöntemidir, yani ilk argümanı olarak bir örneğe referans alır. Doğrudan örnekten çağrıldığında, başvuru dolaylı olarak iletilir, yani belirtmeniz gerekmez:
# you try calling `__init__()` from the class without specifying an instance
# and a TypeError is raised due to the expected but missing reference
A.__init__() # TypeError ...
# you create an instance
a = A()
# you call `__init__()` from that instance and it works
a.__init__()
# you can also call `__init__()` with the class and explicitly pass the instance
A.__init__(a)
2- ararken super()
içinde __init__()
ilk bağımsız değişken olarak alt sınıf ve genel olarak alt sınıf örneğine referans olan bir ikinci değişken gibi ilgi konusu nesne geçmektedir.
super(A, self)
3- Çağrı super(A, self)
, kapsamı çözecek ve self
şimdi ana sınıfın bir örneği gibi uygulanacak bir proxy döndürür . Bu proxy'yi diyelim s
. Bu yana __init__()
bir örnek yöntemi arama s.__init__(...)
dolaylı bir referans geçecek self
ebeveyne ilk bağımsız olduğu gibi __init__()
.
4- aynısını yapmadan super
, bir örneğe ebeveynin sürümüne açıkça bir referans göndermemiz gerekir __init__()
.
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
object.__init__(self, *a, **kw)
super
Sınıf yöntemiyle kullanma
class A(object):
@classmethod
def alternate_constructor(cls, *a, **kw):
print "A.alternate_constructor called"
return cls(*a, **kw)
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return super(B, cls).alternate_constructor(*a, **kw)
Açıklama:
1- Bir sınıf yöntemi doğrudan sınıftan çağrılabilir ve ilk parametresi olarak sınıfa başvuru alır.
# calling directly from the class is fine,
# a reference to the class is passed implicitly
a = A.alternate_constructor()
b = B.alternate_constructor()
2- super()
bir sınıf içinde ebeveyninin sürümüne çözüm bulmak için çağırırken , hangi alt öğenin çözümlemeye çalıştığımızı belirtmek için geçerli alt sınıfı ilk argüman olarak ve ikinci argüman olarak ilgilenilen nesneyi geçmek istiyoruz. bu kapsamı hangi nesneyi uygulamak istediğimizi belirtmek, ki bu genel olarak alt sınıfın kendisine veya alt sınıflarından birine referanstır.
super(B, cls_or_subcls)
3- Çağrı super(B, cls)
kapsamına karar verir A
ve bunu uygular cls
. Yana alternate_constructor()
bir classmethod olan çağrı super(B, cls).alternate_constructor(...)
örtük bir başvuru geçecek cls
ilk argüman olarak A
bir bireyin sürümüalternate_constructor()
super(B, cls).alternate_constructor()
4- aynısını kullanmadan yapmak super()
için, bağlanmamış sürümüne A.alternate_constructor()
(yani fonksiyonun açık sürümüne) bir referans almanız gerekir . Sadece bunu yapmak işe yaramaz:
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return A.alternate_constructor(cls, *a, **kw)
Yukarıdaki A.alternate_constructor()
yöntem işe yaramaz çünkü yöntem A
ilk argümanı olarak örtük bir referans alır . cls
Buraya gönderilen varlık ikinci argüman olacaktır.
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
# first we get a reference to the unbound
# `A.alternate_constructor` function
unbound_func = A.alternate_constructor.im_func
# now we call it and pass our own `cls` as its first argument
return unbound_func(cls, *a, **kw)