गंभीरता से: तुम सच में ऐसा करने के लिए नहीं करना चाहती।
लेकिन, यह समझने के लिए पाइथन के उन्नत उपयोगकर्ताओं के लिए उपयोगी है, इसलिए मैं इसे समझाऊंगा।
सेल और फ्रीवर्स बंद होने पर मान दिए गए मान हैं। उदाहरण के लिए,
def f():
a = 1
def func():
print(a)
return func
f
func
के आधार पर एक बंद देता है, a
के लिए एक संदर्भ के संचय। वह संदर्भ एक सेल में संग्रहीत होता है (वास्तव में एक फ्रीवर में, लेकिन जो कार्यान्वयन तक है)। आप इस की जांच कर सकते हैं:।।।
myfunc = f()
# ('a',)
print(myfunc.__code__.co_freevars)
# (<cell at 0xb7abce84: int object at 0x82b1de0>,)
print(myfunc.__closure__)
("सेल" और "freevars" बहुत समान हैं Freevars नाम, जहां कोशिकाओं अनुक्रमित है है वे दोनों func.__closure__
में जमा हो जाती है, कोशिकाओं पहले आने के साथ कर रहे हैं हम केवल बारे में परवाह यहाँ freevars
, के बाद से है कि क्या __class__
है।)
एक बार जब आप इसे समझ लेंगे, तो आप देख सकते हैं कि सुपर() वास्तव में कैसे काम करता है। किसी भी समारोह को बंद करने में शामिल है कि super
के लिए एक कॉल वास्तव में है, __class__
नाम के एक freevar साथ (जो भी करता है, तो आप __class__
अपने आप का उल्लेख जोड़ा जाता है):
class foo:
def bar(self):
print(__class__)
(चेतावनी:। यह वह जगह है जहां चीजें बुराई मिल)
ये कक्ष func.__closure__
में दिखाई दे रहे हैं, लेकिन यह केवल पढ़ने के लिए है; आप इसे बदल नहीं सकते इसे बदलने का एकमात्र तरीका एक नया फ़ंक्शन बनाना है, जो types.FunctionType
कन्स्ट्रक्टर के साथ किया जाता है। हालांकि, आपके __init__
फ़ंक्शन में __class__
फ्रीवर नहीं है - इसलिए हमें एक को जोड़ने की आवश्यकता है। इसका मतलब है कि हमें एक नया कोड ऑब्जेक्ट भी बनाना है।
नीचे कोड यह करता है। मैंने प्रदर्शन उद्देश्यों के लिए बेस क्लास B
जोड़ा। यह कोड कुछ धारणाएं बनाता है, उदाहरण के लिए। कि __init__
में पहले से ही एक फ्री वैरिएबल नहीं है जिसका नाम __class__
है।
यहां एक और हैक है: सेल प्रकार के लिए एक कन्स्ट्रक्टर प्रतीत नहीं होता है। इसके आसपास काम करने के लिए, एक डमी फ़ंक्शन C.dummy
बनाया गया है जिसमें सेल वैरिएबल की आवश्यकता है।
import types
class B(object):
def __init__(self):
print("base")
class C(B):
def dummy(self): __class__
def __init__(self):
print('calling __init__')
super().__init__()
def MakeCodeObjectWithClass(c):
"""
Return a copy of the code object c, with __class__ added to the end
of co_freevars.
"""
return types.CodeType(c.co_argcount, c.co_kwonlyargcount, c.co_nlocals,
c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names,
c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno,
c.co_lnotab, c.co_freevars + ('__class__',), c.co_cellvars)
new_code = MakeCodeObjectWithClass(__init__.__code__)
old_closure = __init__.__closure__ or()
C.__init__ = types.FunctionType(new_code, globals(), __init__.__name__,
__init__.__defaults__, old_closure + (C.dummy.__closure__[0],))
if __name__ == '__main__':
c = C()
"क्या यह सेल मैन्युअल रूप से सेट करना संभव है"? जब आपने यह कोशिश की, तो क्या हुआ? –
लेकिन फ़ंक्शन को परिभाषित करने के बाद मैं इस सेल तक कैसे पहुंच सकता हूं? '__init __.__ class__' निश्चित रूप से कुछ और है। मैंने अब इसे स्पष्ट करने के लिए प्रश्न संपादित किया है। – nikow
आप कक्षा के बाहर समारोह को परिभाषित क्यों करना चाहते हैं? यदि आप किसी फ़ंक्शन का पुन: उपयोग करना चाहते हैं, या किसी फ़ंक्शन को कई बार विधि के रूप में उपयोग करना चाहते हैं, तो आप यह चाहते हैं। आप उन चीजों को नहीं कर सकते हैं और 'सुपर (...)' सही ढंग से उपयोग कर सकते हैं। और यदि आप रनटाइम पर कक्षा को संशोधित कर रहे हैं, तो आप इसे आसानी से हार्डकोड कर सकते हैं। –