2015-06-24 4 views
8

में वैश्विक चरणीय खोज को अक्षम करें संक्षेप में, प्रश्न: क्या पाइथन को मौजूदा दायरे के बाहर चर को देखने से रोकने का कोई तरीका है?पाइथन

विवरण:

अजगर बाहरी कार्यक्षेत्रों में चर परिभाषा के लिए लग रहा है कि अगर वे वर्तमान क्षेत्र में परिभाषित नहीं कर रहे हैं। इस प्रकार, इस तरह कोड जब सावधान नहीं किया जा रहा तोड़ने के लिए पुनर्रचना के दौरान उत्तरदायी होगा:

def line(x, a, b): 
    return a + x * b 

a, b = 1, 1 
y1 = line(1, a, b) 
y2 = line(1, 2, 3) 

अगर मैं समारोह तर्क का नाम बदला है, लेकिन उन्हें समारोह शरीर के अंदर का नाम बदलने की भूल गया, कोड अभी भी चल पाएंगे:

def line(x, a0, b0): 
    return a + x * b # not an error 

a, b = 1, 1 
y1 = line(1, a, b) # correct result by coincidence 
y2 = line(1, 2, 3) # wrong result 

मुझे पता है it is bad practice to shadow names from बाहरी क्षेत्रों। हालांकि, वहाँ क्यों इस वैसे भी किया जाता है कुछ कारण हैं:

    कभी कभी
  • अर्थपूर्ण हो सकता है एक ही नाम है, क्योंकि वे एक ही बात
  • एक सार्थक चर नाम से बाहर चला सकता है का उल्लेख
  • आलस्य

क्या पाइथन को मौजूदा दायरे के बाहर चर को देखने से रोकने का कोई तरीका है? (ताकि तक पहुँचने a या b दूसरे उदाहरण में एक त्रुटि को जन्म देती है।)

आलसी होने के कारण, मैं एक समाधान है कि बार-बार बॉयलर-प्लेट कोड :)

बिना काम करता है पसंद करेंगे, तो इस मुद्दे को अस्पष्ट है पायथन संस्करण के संदर्भ में, मैं ज्यादातर पायथन 3.3 और उससे ऊपर में रूचि रखता हूं।

+2

नहीं, नहीं है। अन्यथा कोई अंतर्निहित कभी काम नहीं करेगा। –

+1

पायथन को तोड़ने की कोशिश करने के बजाय बेहतर समाधान * उचित परीक्षण * का उपयोग करना है। –

+2

अंतिम तीन पंक्तियों को एक और समारोह में डाल दिया ... – LittleQ

उत्तर

3

नहीं, आप पाइथन को वैश्विक दायरे में नाम न देखने के लिए नहीं बता सकते हैं।

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

वैश्विक लुकअप को तोड़ने की कोशिश करने के बजाय, अपना वैश्विक नामस्थान साफ़ रखें। उन ग्लोबल्स को न जोड़ें जिन्हें आपको मॉड्यूल में अन्य स्कॉप्स के साथ साझा करने की आवश्यकता नहीं है। उदाहरण के लिए main() फ़ंक्शन का उपयोग करें, वास्तव में केवल स्थानीय लोगों को समेकित करने के लिए।

इसके अलावा, unittesting जोड़ें। बिना रिफैक्टरिंग (यहां तक ​​कि केवल कुछ) परीक्षण हमेशा अन्यथा बग बनाने के लिए प्रवण होते हैं।

+2

मैंने हमेशा पुराने सी अभ्यास के संबंध में पाइथन स्क्रिप्ट्स में 'मुख्य()' फ़ंक्शन का उपयोग माना है। वैश्विक नेमस्पेस प्रदूषण के संदर्भ में सोचने से मुझे अब इसे एक अलग प्रकाश में देखा जाता है। धन्यवाद :) – kazemakase

1

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

प्रैक्टिस में, अनावश्यक वैश्विक चर बनाने से बचने के लिए, अपना कोड main() फ़ंक्शन में ले जाएं।

यदि आप ग्लोबल्स का उपयोग करते हैं क्योंकि कई कार्यों को साझा स्थिति में हेरफेर करने की आवश्यकता होती है तो कोड को कक्षा में ले जाएं।

8

हाँ, शायद नहीं सामान्य रूप में। हालांकि आप इसे कार्यों के साथ कर सकते हैं।

बात आप क्या करना चाहते समारोह के रिक्त वैश्विक है। आप वैश्विक स्थान नहीं ले सकता है और आप इसे सामग्री दी गई है बदलना चाहते हैं ( होगा कि सिर्फ वैश्विक चर और कार्यों से छुटकारा पाने के becaus) नहीं करना चाहती।

हालांकि: यदि आप क्रम में समारोह वस्तुओं बना सकते हैं। कन्स्ट्रक्टर types.FunctionType((code, globals[, name[, argdefs[, closure]]]) जैसा दिखता है।

def line(x, a0, b0): 
    return a + x * b # will be an error 

a, b = 1, 1 
y1 = line(1, a, b) # correct result by coincidence 

line = types.FunctionType(line.__code__, {}) 
y1 = line(1, a, b) # fails since global name is not defined 

आप निश्चित रूप से इस अपनी खुद की डेकोरेटर को परिभाषित करते हुए साफ कर सकते हैं: वहाँ आप ग्लोबल नेम स्पेस की जगह ले सकता बोल आप वैश्विक चर का उपयोग करने के लिए यह न करे नहीं है

import types 
noglobal = lambda f: types.FunctionType(f.__code__, {}) 

@noglobal 
def f(): 
    return x 

x = 5 
f() # will fail 

कड़ाई से, आप बस बनाने समारोह का मानना ​​है कि वैश्विक नामस्थान में कोई चर नहीं है। असल में आप स्थिर वैरिएबल को अनुकरण करने के लिए इसका भी उपयोग कर सकते हैं क्योंकि यदि यह एक वैरिएबल को वैश्विक होने की घोषणा करता है और इसे असाइन करता है तो यह वैश्विक नामस्थान के अपने स्वयं के सैंडबॉक्स में समाप्त हो जाएगा।

आप ग्लोबल नेम स्पेस का हिस्सा उपयोग करने में सक्षम होना चाहते हैं तो आप क्या यह देखना चाहते हैं के साथ काम करता है वैश्विक सैंडबॉक्स पॉप्युलेट करने के लिए की आवश्यकता होगी।

+0

इस तरह कुछ ऐसा था जो सवाल पूछते समय मूल रूप से मेरे मन में था। हालांकि, केवल एक मुख्य समारोह का उपयोग करके मेरी वास्तविक जरूरतों को बेहतर बनाता है। – kazemakase

+0

महान जवाब! मैंने इसे आयात और कार्यों को परिभाषित रखने के लिए थोड़ा बढ़ाया: https://gist.github.com/ax3l/59d92c6e1edefcef85ac2540eb056da3 – Ax3l