अधिकांश प्रसिद्ध ओओ भाषाओं में, एक अभिव्यक्ति की तरह SomeClass(arg1, arg2)एक नया उदाहरण आवंटित करेगा, उदाहरण की विशेषताओं को इनिशियलाइज़ करेगा, और फिर इसे वापस करेगा।
अधिकांश प्रसिद्ध OO भाषाओं में, "उदाहरण की विशेषताओं को इनिशियलाइज़ करें" भाग को एक कंस्ट्रक्टर को परिभाषित करके प्रत्येक वर्ग के लिए अनुकूलित किया जा सकता है , जो मूल रूप से कोड का एक ब्लॉक है जो नए इंस्टेंस पर काम करता है (कंस्ट्रक्टर एक्सप्रेशन के लिए दिए गए तर्कों का उपयोग करके) ) जो भी प्रारंभिक शर्तें वांछित हैं, उन्हें स्थापित करने के लिए। पायथन में, यह कक्षा की __init__विधि से मेल खाती है ।
पायथन का __new__"एक नया उदाहरण आवंटित करें" भाग के समान प्रति-वर्ग अनुकूलन से कम और कुछ भी नहीं है। यह निश्चित रूप से आपको असामान्य चीजें करने की अनुमति देता है जैसे कि किसी नए को आवंटित करने के बजाय मौजूदा उदाहरण को वापस करना। इसलिए पायथन में, हमें वास्तव में इस हिस्से के बारे में नहीं सोचना चाहिए क्योंकि आवश्यक रूप से आवंटन शामिल है; हम सभी की आवश्यकता है कि __new__कहीं से एक उपयुक्त उदाहरण के साथ आता है।
लेकिन यह अभी भी नौकरी का केवल आधा हिस्सा है, और पायथन प्रणाली के लिए यह जानने का कोई तरीका नहीं है कि कभी-कभी आप नौकरी के दूसरे भाग ( __init__) को बाद में चलाना चाहते हैं और कभी-कभी आप नहीं करते हैं। यदि आप उस व्यवहार को चाहते हैं, तो आपको स्पष्ट रूप से कहना होगा।
अक्सर, आप रिफ्लेक्टर कर सकते हैं ताकि आपको केवल ज़रूरत हो __new__, या इसलिए आपको ज़रूरत नहीं है __new__, या इसलिए कि __init__पहले से ही एक प्रारंभिक ऑब्जेक्ट पर अलग तरह से व्यवहार करता है। लेकिन अगर आप वास्तव में चाहते हैं, तो पायथन वास्तव में आपको "नौकरी" को फिर से परिभाषित करने की अनुमति देता है, ताकि SomeClass(arg1, arg2)जरूरी कॉल __new__उसके बाद न हो __init__। ऐसा करने के लिए, आपको मेटाक्लस बनाने की जरूरत है, और इसकी __call__विधि को परिभाषित करें ।
एक मेटाक्लास सिर्फ एक वर्ग का वर्ग है। और एक वर्ग की __call__विधि नियंत्रित करती है कि जब आप कक्षा के उदाहरण कहते हैं तो क्या होता है। तो एक metaclass ' __call__विधि नियंत्रण क्या होता है जब आप एक वर्ग कहते हैं; यानी यह आपको शुरू से अंत तक इंस्टेंस-निर्माण तंत्र को फिर से परिभाषित करने की अनुमति देता है । यह वह स्तर है जिस पर आप एकल स्तर पर गैर-मानक आवृत्ति निर्माण प्रक्रिया जैसे कि सिंगलटन पैटर्न को सर्वाधिक प्रभावी ढंग से लागू कर सकते हैं। वास्तव में, कोड की 10 से कम लाइनों के साथ आप एक Singletonमेटाकाॅल को लागू कर सकते हैं जो तब आपको __new__ सभी के साथ फ्यूज करने की आवश्यकता नहीं होती है , और किसी भी अन्यथा-सामान्य वर्ग को एक एकल में केवल जोड़कर बदल सकते हैं __metaclass__ = Singleton!
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
हालांकि यह शायद इस स्थिति के लिए वास्तव में वारंट की तुलना में गहरा जादू है!