2012-08-22 11 views
6

में ग्लोबल्स और सिंगलेट्स मेरे पास कुछ पायदान हैं जो मेरे पायथन एप्लिकेशन में व्यापक हैं और जिनके पास केवल एक वैश्विक उदाहरण होना चाहिए (जैसे लॉगर, डीबीकनेक्शन)। पायथन कक्षा में स्थैतिक चर/विधियों का समर्थन नहीं करता है, इसलिए यहां एक सिंगलटन बनाने के लिए सामान्य जावा/सी ++ तरीका काम नहीं करता है। मैंने पाइथन में सिंगलटन को लागू करने के विकल्पों की तलाश की है। मैं एक साधारण (यदि संभव हो तो कोई मेट्रोग्रामिंग नहीं) और स्वच्छ कार्यान्वयन चाहता हूं। यह अच्छा लग रहा है:पाइथन

class MyClass(object): 
    def a(): 
     pass 

singleton = MyClass() 

सिंगलटन का उपयोग के रूप में

import myClass 
myClass.singleton.a() 

प्रत्यक्ष काम एक रचना समारोह द्वारा प्रतिस्थापित किया जा सकता है अगर वस्तु प्रारंभ इतना आसान नहीं है आसान होगा।

मैं मॉड्यूल स्कोप में getInstance() भी बना सकता हूं और हमेशा myObj प्राप्त करने के लिए इसका उपयोग कर सकता हूं।

प्रश्न 1) यह ठीक काम करता है? मॉड्यूल कोड (myObj असाइनमेंट) केवल पहली बार चलाता है जब इसे किसी अन्य मॉड्यूल में आयात किया जाता है और जब भी मैं इस मॉड्यूल को कहीं भी आयात करता हूं तो myObj नहीं बनाया जाएगा?

मैंने देखा है कि एक वैकल्पिक विधि एक ग्लोबल्स मॉड्यूल का उपयोग करना है। की तरह कुछ:

from myClass1 import MyClass1 
from myClass2 import MyClass2 

myObj1 = MyClass1() 
myObj2 = MyClass2() 

इस का उपयोग करते हुए:

import globals 
globals.myObj1.a() 

मैं पहली बार विकल्प पसंद करते हैं।

प्रश्न 2) 2 समाधानों के बीच, आप क्या सलाह देते हैं?

प्रश्न 3) एक तीसरा समाधान कई वर्गों/कार्यों के लिए लॉगर जैसे व्यापक वस्तुओं को पारित करेगा, लेकिन यह एक अच्छा समाधान नहीं है। क्या यहां कोई बेहतर समाधान नहीं बताया गया है?

मैं वैश्विक चर और सिंगलेट्स का उपयोग करने के डाउनसाइड्स से अवगत हूं। हालांकि, मेरे आवेदन में वैश्विक स्थिति होने का कोई बड़ा मुद्दा नहीं है। मैं ऐसे समाधान पसंद करूंगा जिनमें कोड स्पष्टता हो और उपयोग करने में आसान हो।

+0

आपके प्रश्न का प्रीमियर गलत है। पहला, पायथन स्थैतिक तरीकों और चर का समर्थन करता है। दूसरा, आप लॉगिंग और डेटाबेस पहुंच के लिए मौजूदा मानक पुस्तकालयों का उपयोग क्यों नहीं कर रहे हैं? –

+0

पायथन सीधे स्थिर तरीकों/चर का समर्थन करता है (कोई एनोटेशन हैक नहीं)? आपका दूसरा प्रश्न इस मुद्दे से विचलित हो जाता है (सिंगलटन कार्यान्वयन), किसी एकल वर्ग द्वारा लॉगिंग/डीबी एक्सेस क्लास को प्रतिस्थापित करें और यह किसी एप्लिकेशन में व्यापक रूप से उपयोग किया जाता है। –

उत्तर

6

यदि आप logger कक्षा चाहते हैं जिसमें केवल एक उदाहरण है, तो बस इसे एक अलग मॉड्यूल बनाएं।

# In logging.py 
def log(msg): 
    print msg 

तब किसी भी स्क्रिप्ट से आप लॉग इन करना चाहते हैं।

from logging import log 
log("A critical error occured.") 
+1

मेरे पास मेरे लॉगर क्लास (जैसे लॉग फ़ाइल नाम) में विशेषताएँ हैं। यदि मैं मॉड्यूल फ़ंक्शंस में अपनी कक्षा विधियों को बदलता हूं, तो पूर्व श्रेणी विशेषताओं मॉड्यूल चर बन जाएगा। क्या यह कोई समस्या नहीं है? (उदाहरण के लिए, यह उपयोगकर्ता "लॉगिंग आयात * * (गलत मुझे पता है, लेकिन फिर भी) का उपयोग करता है, मेरे चर अनुप्रयोग अनुप्रयोग चर अव्यवस्थित होंगे। –

+0

@ user1550682: एक मॉड्यूल वास्तव में पाइथन में केवल एक सिंगलटन है। यह एक वस्तु है, इसका केवल एक उदाहरण है, और आप इसे किसी अन्य मूल्य की तरह पास कर सकते हैं। इसलिए, कोई समस्या नहीं। –

+5

@ user1550682 - एक ही अंडरस्कोर के साथ अपने निजी चर का उपसर्ग करें। और उन्हें 'आयात *' के साथ आयात नहीं किया जाएगा। कथन। उदाहरण के लिए '_filename =" bla.bla "' – Aesthete

-1

सिंगलेट बनाने के लिए सही जवाब क्या है? मत करो। आपको स्पष्ट रूप से उन सभी चीज़ों का संदर्भ देना चाहिए जिन्हें इसका उपयोग करने की आवश्यकता है। आप कारखाने के कार्यों, रैपर वर्गों और इसी तरह के प्रयासों को कम कर सकते हैं।

भले ही स्क्रीन या लॉगर की तरह कुछ ऐसा हो, जो प्रकृति में वैश्विक है, तो आपको अभी भी यूनिट परीक्षण की अनुमति देने के लिए इसे स्पष्ट रूप से पास करना चाहिए। ध्यान दें कि यह केवल अंतिम डिजाइन का हिस्सा बनने के इरादे से लागू होता है। यदि आपका लॉगर डीबगिंग के लिए एक त्वरित हैक है, तो इसे वैश्विक बनाने के लिए स्वतंत्र महसूस करें।

+0

जैसा कि मेरी मूल पोस्ट में बताया गया है, मैं सिंगलेट्स का उपयोग करने के डाउनसाइड्स से अवगत हूं। उनका उपयोग विवादास्पद है क्योंकि मैंने आज तक उनके बारे में पहले सुना है। किसी एप्लिकेशन में सभी वर्गों और कार्यों (यदि वे कक्षा के बाहर हैं) में लॉगर वैरिएबल पास करना मेरे लिए यूटोपिक लगता है, मैंने कभी ऐसा वास्तविक एप्लिकेशन नहीं देखा है जो इसे करता है। –

+0

मैंने इसे कुछ बार किया है, हालांकि स्वीकार्य रूप से अपेक्षाकृत सरल लिपियों में। और जब मैं इसे और अधिक पूरा कर लेता हूं तो मैं इसे अपने वर्तमान प्रोजेक्ट में करने की योजना बना रहा हूं। लेकिन आप सही हैं कि यह थोड़ा यूटोपिक है। – Antimony

+1

एलन: कई एप्लिकेशन या तो वैश्विक लॉगर इंस्टेंस का उपयोग करते हैं, या इसे सेटिंग मॉड्यूल में पास करते हैं जो एप्लिकेशन के अन्य हिस्सों में आयात किया जाता है। इसके अलावा, कई एप्लिकेशन भी एक ऐप या सेटिंग्स मॉड्यूल पर निर्भर होते हैं, जो पूरे वैरिएबल, सिंगलटन इंस्टेंस या धागे को स्टोर करता है जो पूरे एप्लिकेशन में उपयोग किए जाने वाले हैं। Django और Celery अनुप्रयोगों के दोनों उदाहरण हैं जो यह करते हैं। प्रॉक्सी और राज्य डिज़ाइन पैटर्न का उपयोग करके, यह सिंगलेट्स पर भरोसा करने की आवश्यकता को सरल बनाता है, हालांकि आखिरकार यह एक अलग रूप में होता है। –

0

निम्नलिखित बनाने पर विचार करें:

  1. एक राज्य वर्ग
  2. एक प्रॉक्सी वर्ग

राज्य वर्ग एक धागा है कि एक init में प्रारंभ हो जाएगा पैदा करेगा। पाई मॉड्यूल। राज्य वर्ग में ऐसे विधियां होंगी जो कक्षा के उदाहरणों को थ्रेड में पास करती हैं और इसे कमजोर बना देती हैं।

बाद में, थ्रेड में कक्षा के उदाहरणों तक पहुंचने के लिए प्रॉक्सी क्लास का उपयोग किया जा सकता है। यदि वर्ग ऑब्जेक्ट्स नहीं बनाए जाते हैं, तो प्रॉक्सी वांछित कक्षा का एक उदाहरण बनायेगा और इसे थ्रेड पर सहेज देगा।

इस पैटर्न का उपयोग करके, आप प्रत्येक वर्ग के उदाहरणों की संख्या 1 तक सीमित कर सकते हैं, और यह सुनिश्चित कर सकते हैं कि जब भी आपके आवेदन का कोई हिस्सा चल रहा हो, तो किसी भी उदाहरण को वैश्विक रूप से उपयोग करने की आवश्यकता होती है, बार-बार, इसे फिर से नहीं बनाया जाना चाहिए ।