जब बुला रहे हो super()
किसी क्लासमेथोड के माता-पिता के संस्करण, उदाहरण विधि, या स्टेटमिथोड को हल करने के लिए किया जाता है, तो हम वर्तमान वर्ग को पास करना चाहते हैं जिसका दायरा हम पहले तर्क के रूप में देखते हैं, यह इंगित करने के लिए कि हम किस माता-पिता के दायरे को हल करने का प्रयास कर रहे हैं, और दूसरा तर्क यह बताता है कि हम उस दायरे को लागू करने के लिए किस वस्तु को इंगित करना चाहते हैं।
एक वर्ग पदानुक्रम पर विचार करें A
, B
और C
जहां प्रत्येक वर्ग यह निम्न में से एक की मूल है, और a
, b
और c
प्रत्येक के संबंधित उदाहरणों।
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
एक staticmethod के साथ
जैसे super()
कि __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)
स्पष्टीकरण:
1- भले ही यह सामान्य __new__()
रूप से कॉलिंग क्लास के संदर्भ में अपना पहला परम लेने के लिए है, यह है पायथन में एक क्लासमेथोड के रूप में लागू नहीं किया गया है, बल्कि एक स्टेथमिथोड है। अर्थात, __new__()
सीधे कॉल करते समय किसी कक्षा के संदर्भ को पहले तर्क के रूप में स्पष्ट रूप से पारित किया जाना चाहिए :
# 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()
अभिभावक वर्ग को प्राप्त करने के लिए कॉल करते समय हम बच्चे की कक्षा पास करते हैंA
तो हम को उसके पहले तर्क के रूप में , फिर हम रुचि की वस्तु के संदर्भ में पास करते हैं, इस मामले में यह कक्षा का संदर्भ है A.__new__(cls)
जिसे तब बुलाया गया था। ज्यादातर मामलों में यह बाल वर्ग के संदर्भ में भी होता है। उदाहरण के लिए, कुछ स्थितियों में यह कई पीढ़ी की विरासत के मामले में नहीं हो सकता है।
super(A, cls)
3- चूँकि एक सामान्य नियम __new__()
एक स्थैतिक तत्व है,super(A, cls).__new__
को भी लौटाएगा और इस मामले में स्पष्ट रूप से इंस्ट्रस्ट की वस्तु के संदर्भ सहित सभी तर्कों की आपूर्ति की जानी चाहिए cls
।
super(A, cls).__new__(cls, *a, **kw)
4- बिना बात के एक ही काम करना super
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return object.__new__(cls, *a, **kw)
super
एक इंस्टेंस विधि का उपयोग करना
जैसे super()
भीतर से उपयोग कर रहे हैं__init__()
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
super(A, self).__init__(*a, **kw)
स्पष्टीकरण:
1- __init__
एक उदाहरण विधि है, जिसका अर्थ है कि यह एक उदाहरण के संदर्भ में अपने पहले तर्क के रूप में लेता है। जब उदाहरण से सीधे कॉल किया जाता है, तो संदर्भ को स्पष्ट रूप से पारित किया जाता है, अर्थात क्या आपको इसे निर्दिष्ट करने की आवश्यकता नहीं है:
# 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- जब हम कॉल करते super()
हैं __init__()
तो हम बच्चे के वर्ग को पहले तर्क के रूप में और दूसरे तर्क के रूप में ब्याज की वस्तु के रूप में पास करते हैं, जो सामान्य रूप से बाल वर्ग के उदाहरण के लिए एक संदर्भ है।
super(A, self)
3- कॉल super(A, self)
एक प्रॉक्सी देता है जो दायरे को हल करेगा और इसे लागू करेगा self
जैसे कि यह अब मूल वर्ग का एक उदाहरण है। चलो उस प्रॉक्सी को कॉल करें s
। चूंकि __init__()
एक इंस्टेंस मेथड है, इसलिए कॉल मूल रूप से माता-पिता के पहले तर्क के s.__init__(...)
संदर्भ को पारित करेगाself
__init__()
।
4- बिना super
माता-पिता के संस्करण के स्पष्ट रूप से उदाहरण के संदर्भ में जाने के लिए हमें ऐसा करने की आवश्यकता है __init__()
।
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
object.__init__(self, *a, **kw)
super
क्लासमैथोड के साथ उपयोग करना
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)
स्पष्टीकरण:
1- एक क्लासमेथोड को सीधे क्लास से बुलाया जा सकता है और क्लास के संदर्भ में इसके पहले पैरामीटर के रूप में लिया जाता है।
# 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()
अपने माता-पिता के संस्करण को हल करने के लिए एक क्लासमेथोड के भीतर कॉल करते हैं, तो हम वर्तमान चाइल्ड क्लास को पहले तर्क के रूप में उत्तीर्ण करना चाहते हैं कि यह इंगित करने के लिए कि हम किस माता-पिता के दायरे को हल करने का प्रयास कर रहे हैं, और दूसरे तर्क के रूप में ब्याज की वस्तु। यह इंगित करने के लिए कि हम उस दायरे को किस वस्तु पर लागू करना चाहते हैं, जो सामान्य रूप से स्वयं बाल वर्ग या उसके किसी उपवर्ग का संदर्भ है।
super(B, cls_or_subcls)
3- कॉल super(B, cls)
के दायरे में हल A
होता है और इसे लागू होता है cls
। चूंकि alternate_constructor()
एक क्लासमेथोड है, इसलिए कॉल पहले के संस्करण के पहले तर्क super(B, cls).alternate_constructor(...)
के cls
रूप में एक संदर्भ पारित करेगाA
alternate_constructor()
super(B, cls).alternate_constructor()
4- बिना उपयोग के super()
भी ऐसा करने के लिए आपको अनबाउंड वर्जन A.alternate_constructor()
(यानी फंक्शन का स्पष्ट वर्जन) का संदर्भ लेना होगा। बस ऐसा करने से काम नहीं चलेगा:
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)
ऊपर काम नहीं करेगा क्योंकि A.alternate_constructor()
विधि A
अपने पहले तर्क के रूप में एक अंतर्निहित संदर्भ लेती है। यहां cls
से पारित होना इसका दूसरा तर्क होगा।
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)