एक इफ स्टेटमेंट में इनिशियलाइज़ किए गए वैरिएबल का स्कोप क्या है?


266

मैं पाइथन के लिए नया हूं, इसलिए यह शायद एक साधारण सा प्रश्न है। पायथन फ़ाइल (मॉड्यूल) में निम्न कोड मुझे थोड़ा भ्रमित कर रहा है:

if __name__ == '__main__':
    x = 1

print x

मैंने जिन अन्य भाषाओं में काम किया है, यह कोड एक अपवाद को फेंक देगा, क्योंकि xचर ifकथन के लिए स्थानीय है और इसके बाहर मौजूद नहीं होना चाहिए। लेकिन यह कोड निष्पादित करता है, और प्रिंट करता है 1. क्या कोई इस व्यवहार की व्याख्या कर सकता है? क्या सभी वैरिएबल एक मॉड्यूल ग्लोबल में बनाए गए हैं / पूरे मॉड्यूल के लिए उपलब्ध हैं?


17
एक और मोड़ आप के बारे में पता नहीं हो सकता है: अगर ifसच (यानी, बयान से ऊपर नहीं रखता है __name__है नहीं '__main__' जब आप इसे उच्च-स्तरीय क्रियान्वित करने के बजाय मॉड्यूल आयात उदाहरण के लिए,), तो xकभी नहीं के लिए बाध्य किया गया होगा, और बाद में print xबयान एक फेंक देते हैं NameError: name 'x' is not defined
संता

जवाबों:


301

पायथन वेरिएबल्स को अंतरतम फ़ंक्शन, क्लास, या मॉड्यूल में स्कूप किया जाता है जिसमें वे असाइन किए जाते हैं। नियंत्रण ब्लॉकों जैसे ifऔर whileब्लॉक की गणना नहीं होती है, इसलिए एक के अंदर असाइन किया गया एक चर ifअभी भी एक फ़ंक्शन, वर्ग या मॉड्यूल के लिए स्कूप किया गया है।

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



105

हां, वे समान "स्थानीय दायरे" में हैं, और वास्तव में इस तरह का कोड पायथन में आम है:

if condition:
  x = 'something'
else:
  x = 'something else'

use(x)

xउदाहरण के लिए, सी या जावा में होने वाली स्थिति से पहले नोट या घोषित नहीं किया गया है।

दूसरे शब्दों में, पायथन में ब्लॉक-स्तरीय स्कोप नहीं होते हैं। हालांकि, सावधान रहें, जैसे कि उदाहरण के साथ

if False:
    x = 3
print(x)

जो स्पष्ट रूप से एक NameErrorअपवाद को बढ़ाएगा ।


42

अजगर में स्कोप इस आदेश का पालन करता है:

  • स्थानीय गुंजाइश खोजें

  • किसी भी संलग्नक कार्य के दायरे को खोजें

  • वैश्विक गुंजाइश खोजें

  • बिल्ट-इन खोजें

( स्रोत )

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


9

जैसा कि एली ने कहा, पायथन को परिवर्तनीय घोषणा की आवश्यकता नहीं है। सी में आप कहेंगे:

int x;
if(something)
    x = 1;
else
    x = 2;

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

एकमात्र कारण यह है कि एक सांख्यिकीय रूप से टाइप की गई भाषा ifइस समस्या के कारण बयानों के बाहर चर घोषित करने तक सीमित है। गतिशील को गले लगाओ!


9

C जैसी भाषाओं के विपरीत, एक पायथन वैरिएबल पूरे फ़ंक्शन (या वर्ग, या मॉड्यूल) के लिए गुंजाइश है जहां यह प्रकट होता है, न कि केवल अंतरतम "ब्लॉक" में। यह ऐसा है जैसे आपने int xफ़ंक्शन (या वर्ग, या मॉड्यूल) के शीर्ष पर घोषित किया है, सिवाय इसके कि पायथन में आपको चर घोषित करने की आवश्यकता नहीं है।

ध्यान दें कि चर xका अस्तित्व केवल रनटाइम पर जांचा जाता है - अर्थात, जब आप print xस्टेटमेंट प्राप्त करते हैं। यदि __name__बराबर नहीं था, "__main__"तो आपको एक अपवाद मिलेगा NameError: name 'x' is not defined:।


कक्षाएं एक गुंजाइश नहीं बनाती हैं; एक कक्षा में एक "स्थानीय" चर को सृजन पर बस वर्ग के हुक्म में जोड़ा जाता है।
Chepner

3

हाँ। यह forस्कोप के लिए भी सही है। लेकिन निश्चित रूप से कार्य नहीं।

आपके उदाहरण में: यदि ifकथन में स्थिति झूठी है, xहालांकि इसे परिभाषित नहीं किया जाएगा।


2

आप इस कोड को कमांड लाइन से निष्पादित कर रहे हैं इसलिए ifस्थितियां सत्य हैं और xसेट की गई हैं। की तुलना करें:

>>> if False:
    y = 42


>>> y
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    y
NameError: name 'y' is not defined

0

और ध्यान दें कि चूंकि पायथन प्रकार केवल रनटाइम पर जांचे जाते हैं, इसलिए आपके पास कोड हो सकता है जैसे:

if True:
    x = 2
    y = 4
else:
    x = "One"
    y = "Two"
print(x + y)

लेकिन मुझे उन अन्य तरीकों के बारे में सोचने में परेशानी हो रही है जिनमें टाइप के मुद्दों के कारण कोड बिना किसी त्रुटि के काम करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.