2012-09-28 16 views
9

स्टैक ओवरफ़्लो में पाइथन में वैश्विक चर के संबंध में बहुत सारे प्रश्न हैं, और ऐसा लगता है कि अन्य भाषाओं से आने वाले लोगों के लिए कुछ भ्रम उत्पन्न होता है। स्कोपिंग नियम वास्तव में काम नहीं करते हैं कि अन्य पृष्ठभूमि से बहुत से लोग उन्हें उम्मीद करते हैं।पायथन में वैश्विक चर की आवृत्ति?

उसी समय, कोड कक्षा स्तर पर इतना नहीं, बल्कि मॉड्यूल स्तर पर व्यवस्थित किया जाना है। इसलिए जब कक्षाओं में सबकुछ अनिवार्य रूप से निहित नहीं होता है, तो राज्य जो अन्यथा सदस्य चर में पाया जाता है, मॉड्यूल-स्तरीय चर में जा सकता है।

तो मेरे सवाल का 2 हिस्सा है:

1) मैं (विशेष रूप से उन कार्यों के भीतर से स्थापित करने और वैश्विक कीवर्ड का उपयोग) वैश्विक का उपयोग न किया जाना चाहिए?

2) यदि # 1 हां है, तो क्या ऐसे सामान्य पैटर्न हैं जहां उनका उपयोग होने की उम्मीद है?

मैं ऐसी जगह पर काम करता हूं जहां कई अलग-अलग भाषाएं बढ़ती हैं और मैं भ्रम को कम करना चाहता हूं और यह सुनिश्चित कर सकता हूं कि बाद में पाइथोनिस्ट मुझसे नफरत नहीं करेंगे।

किसी भी रचनात्मक इनपुट के लिए धन्यवाद।

+0

और वहाँ अजगर 3.x में 'nonlocal' :) –

+0

@Jon क्लेमेंट्स है: तो क्या हुआ? – martineau

उत्तर

7

मैं आपको सलाह देता हूं कि आप इस ब्लॉग पोस्ट को Singletons and their Problems in Python शीर्षक से पढ़ें। इसने मुझे वैश्विक चर के उपयोग पर पुनर्विचार करने का कारण बना दिया है। कुछ विकल्प उद्धरण:

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

यह सही है: एक पायथन मॉड्यूल एक सिंगलटन है। और यह सिंगलटन पैटर्न की एक ही समस्या साझा करता है कि यह थोड़ा और खराब है।

और यहाँ ऐसे साझा किए गए राज्य होने समस्याओं में से एक उदाहरण के कारण हो सकता है:

अप्रासंगिक बातों के बारे में बात नहीं करने के लिए, चलो मानक पुस्तकालय से मॉड्यूल में से एक पर एक नजर है में, mimetypes मॉड्यूल।

inited = False 

def init(files=None): 
    global inited 
    db = MimeTypes() 
    ... 

यह Mimetypes मॉड्यूल है कि अजगर के साथ जहाज, बस अधिक रक्तमय विवरण के साथ हटाया से वास्तविक कोड है:

एक नज़र डालें। मुद्दा यह है कि साझा राज्य है। और साझा स्थिति एक बुलियन ध्वज है जो सही है यदि मॉड्यूल प्रारंभ किया गया था या गलत नहीं था तो यह गलत था। अब वह विशेष मामला शायद समस्याग्रस्त नहीं है (मेरा विश्वास करो, यह है) क्योंकि mimetypes खुद को शुरू करता है, लेकिन आप देख सकते हैं कि init फ़ंक्शन में कोई फ़ाइल पैरामीटर है। यदि आप उस फ़ंक्शन में फ़ाइलों की एक सूची पास करते हैं, तो यह उन फ़ाइलों से माइम जानकारी के साथ स्मृति में माइम डेटाबेस को पुन: प्रारंभ करेगा। अब कल्पना अगर आप दो अलग-अलग स्रोतों से Mimetypes आरंभ दो पुस्तकालयों ... है क्या होगा

एक काफी आम पैटर्न है यही कारण है, और मैं इसे अपने आप किया है ... लेकिन उदाहरण करने के लिए यह होगा एक बेहतर तरीका के लिए : init एक वर्ग का एक उदाहरण देता है जो सभी विधियों को लागू करता है, और कोड के अन्य हिस्सों init को विभिन्न पैरामीटर के साथ एक अलग उदाहरण प्राप्त करने के लिए पूर्व में हस्तक्षेप नहीं कर सकता है। "नकारात्मक" यह है कि आपको इस उदाहरण को किसी भी कोड पर पास करना है जो एक नया प्रारंभ नहीं करना चाहता है, लेकिन उस "नकारात्मक" के ऊपर की ओर यह है कि यह स्पष्ट करता है कि आपकी निर्भरता क्या है।

वैसे भी, संक्षेप में, मैं जितना संभव हो उससे बचने की कोशिश करता हूं, लेकिन अगर आप एक अंतर्निहित सिंगलटन वाले कोड के साथ ठीक हैं तो इसके लिए जाएं।

+1

एक सिंगलटन के उदाहरणों के रूप में मॉड्यूल का उपयोग करने की एक और बड़ी सीमा है कि, एक __init __() 'विधि के साथ एक वर्ग के विपरीत जिसे कॉल किया जाएगा और संभवतः तर्क पारित किया जाएगा, प्रारंभिक 'आयात' पर बनाए गए (एकल) उदाहरण के निर्माण को प्रभावित/नियंत्रित करना मुश्किल है। – martineau

+0

@ क्लाउडियो धन्यवाद, इस उत्तर ने मुझे उम्मीद से अधिक दिया :)। – MrFox

2

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

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

3

संक्षेप में, हाँ, आपको global कीवर्ड का उपयोग करने से परहेज करना चाहिए। यह किसी कारण के लिए भाषा में हो सकता है लेकिन मैं आम तौर पर इसे कोड गंध मानता हूं - यदि आपके पास कुछ राज्य है जिसे आप रखना चाहते हैं, तो इसे कक्षा में समाहित करें। global का उपयोग करने से यह बहुत कम नाजुक है।

+1

मैं इसे 'वैश्विक' का उपयोग करने के लिए कठिन और तेज़ नियम के रूप में नहीं लेता हूं। कक्षा के उदाहरण में अपने सभी राज्य को रखना आसान है, और यदि आपको कभी भी कक्षा के एक से अधिक उदाहरण बनाने की आवश्यकता है, तो आपको अपने भाग्यशाली सितारों का शुक्रिया अदा करना चाहिए कि आप उन्हें एक-दूसरे पर कदम नहीं उठा रहे हैं। यदि राज्य को वास्तव में आम होने की आवश्यकता है, तो इसे कक्षा पदानुक्रम में एक स्तर पर ले जाएं। – Dave

+0

मैं कभी-कभी 'foo = [globalvar]' करता हूं और फिर कार्यों के भीतर 'foo [0]' प्राप्त करता हूं और इसलिए मुझे उस 'वैश्विक' कीवर्ड का उपयोग करने की आवश्यकता नहीं है। यह इस तरह से अधिक स्पष्ट करता है कि मैं एक वैश्विक varibale कारण का उपयोग कर रहा हूं, मुझे इसे 'विशेष रूप से' इलाज करना है, लेकिन यह अभी भी बहुत बदसूरत है, वैश्विक चर का उपयोग करने की तरह – Claudiu

3

मैं अपने अन्य सवाल पर कि टिप्पणी की है, तो यहाँ मेरी 2 Cents हैं:

अजगर ऑब्जेक्ट ओरिएंटेड है, लेकिन आप इसका इस्तेमाल करने की जरूरत नहीं है। लेकिन तुम, तुम कक्षा के इस तंत्र का फायदा उठाने सकता है करने के लिए कुछ गुण धारण करने के लिए चुनते हैं:

cfg = Config() 

और फिर का उपयोग कर उन तक पहुँचने:

class Config(): 
""" 
hold some vars for example. 
""" 
def __init__(self): 
    self.CONFIG_LOG_FILE_DIR='/tmp2/ozn/venus_mon_log/' 
    self.DATE_FORMAT="%Y%m%d" 
    #self.FILE_NAME_BASE_TEMPLATE=eval('datetime.datetime.now().strftime(self.DATE_FORMAT)')+'-venus_utilization.log' 
    self.FILE_NAME_BASE_TEMPLATE='venus_utilization.log' 
    self.FILE_NAME=self.CONFIG_LOG_FILE_DIR+self.FILE_NAME_BASE_TEMPLATE 
    self.MAX_FILE_SIZE=1024*1024*50 # in Byte, 50 in MB. 

आप एक उदाहरण है कि आप गुण तक पहुँच देता है बना सकते हैं :

cfg.MAX_FILE_SIZE 

या यहाँ तक कि उन्हें बदलने:

cfg.MAX_FILE_SIZE=50000 
    cfg.MAX_FILE_SIZE=calculateNewSize() 

और इतने पर ... तुम भी तरह सामान कर सकता है:

# this will print all items that an instance has  
if options.debug: 
    print "DEBUG INFO:" 
    for k,v in vars(cfg).iteritems(): 
     print k,v 
संबंधित मुद्दे