यहां आप दो बुनियादी समस्याएं चला रहे हैं:
__xxx__
तरीकों को केवल कक्षा पर देखा जाता है
TypeError: can't set attributes of built-in/extension type 'module'
(1) का मतलब है कि किसी भी समाधान के लिए इस बात का भी ध्यान रखना होगा कि किस मॉड्यूल की जांच की जा रही है, अन्यथा प्रत्येक मॉड्यूल के पास उदाहरण-प्रतिस्थापन व्यवहार होगा; और (2) का मतलब है कि (1) संभव भी नहीं है ... कम से कम सीधे नहीं।
सौभाग्य से, sys.modules के बारे में अचार नहीं है कि वहां क्या चल रहा है इसलिए एक आवरण काम करेगा, लेकिन केवल मॉड्यूल एक्सेस के लिए (यानी import somemodule; somemodule.salutation('world')
, समान-मॉड्यूल एक्सेस के लिए आपको प्रतिस्थापन वर्ग से विधियों को globals()
भटकना होगा और उन्हें ei के साथ जोड़ना होगा ; वर्ग पर कस्टम विधि (मुझे पसंद है .export()
) या एक जेनेरिक फ़ंक्शन के साथ (जैसे कि पहले से ही उत्तर के रूप में सूचीबद्ध)। एक बात का ध्यान रखें: यदि रैपर हर बार एक नया उदाहरण बना रहा है, और ग्लोबल्स समाधान नहीं है। आप अलग-अलग व्यवहार के साथ अंत करते हैं। ओह, और आपको एक ही समय में दोनों का उपयोग करने की आवश्यकता नहीं है - यह एक या दूसरे है।
अपडेट करें
से गुइडो van Rossum :
वास्तव में एक हैक है जिसे कभी-कभी उपयोग किया जाता है और सिफारिश की जाती है: एक मॉड्यूल वांछित कार्यक्षमता के साथ एक वर्ग को परिभाषित कर सकता है, और फिर अंत में, उस वर्ग के उदाहरण के साथ खुद को sys.modules में बदल सकता है (या वर्ग के साथ, यदि आप जोर देते हैं , लेकिन यह आम तौर पर कम उपयोगी है)। उदाहरण के लिए:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
यह काम करता है क्योंकि आयात मशीनरी सक्रिय रूप से इस हैक को सक्षम कर रही है, और जैसा कि इसका अंतिम चरण वास्तविक मॉड्यूल को sys.modules से बाहर निकालता है, इसे लोड करने के बाद। (यह कोई दुर्घटना नहीं है। हैक बहुत पहले प्रस्तावित किया गया था और हमने तय किया कि हम इसे आयात मशीनरी में समर्थन के लिए पर्याप्त पसंद करते हैं।)
इसलिए जो आप चाहते हैं उसे पूरा करने के लिए स्थापित तरीका आपके मॉड्यूल में एक एकल वर्ग बनाना है, और मॉड्यूल के अंतिम कार्य के रूप sys.modules[__name__]
में आपकी कक्षा के एक उदाहरण के साथ प्रतिस्थापित किया जाता है - और अब आप आवश्यकतानुसार __getattr__
/ __setattr__
/ के साथ खेल सकते हैं __getattribute__
।
नोट 1 : यदि आप इस कार्यक्षमता का उपयोग करते हैं, तो मॉड्यूल में कुछ भी, जैसे ग्लोबल्स, अन्य फ़ंक्शन आदि, sys.modules
असाइनमेंट किए जाने पर खो जाएगा - इसलिए सुनिश्चित करें कि प्रतिस्थापन वर्ग के अंदर आवश्यक सभी चीजें हैं।
नोट 2 : समर्थन करने के लिए from module import *
आपको __all__
कक्षा में परिभाषित होना चाहिए ; उदाहरण के लिए:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
आपके पायथन संस्करण के आधार पर, इससे हटने के अन्य नाम भी हो सकते हैं __all__
। set()
यदि अजगर 2 अनुकूलता की जरूरत नहीं है छोड़ा जा सकता है।