पायथन नॉनक्लॉक स्टेटमेंट


341

पायथन nonlocalकथन क्या करता है (पायथन 3.0 और बाद में)?

आधिकारिक पायथन वेबसाइट पर कोई प्रलेखन help("nonlocal")नहीं है और यह भी काम नहीं करता है।


4
इस प्रश्न पर एक नज़र डालें: stackoverflow.com/questions/1414304/local-functions-in-python
मैट जॉइनर

18
यहाँ nonlocal के लिए आधिकारिक पायथन वेबसाइट प्रलेखन है: docs.python.org/3/reference/… (यह दस्तावेज़ीकरण Python 3.0 के बाद से उपलब्ध है, इसलिए ओपी का दावा है कि कोई आधिकारिक दस्तावेज गलत नहीं था)
wkschwartz

3
"There is no documentation for nonlocal".असल में, आप help(keyword_in_string)पायथन 3 और इसके बाद के संस्करण के लिए कर सकते हैं
ytpillai

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

जवाबों:


473

इसकी तुलना करें, बिना उपयोग के nonlocal:

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

इस के लिए, का उपयोग करते हुए nonlocal, जहां inner()'s xअब भी है outer()की x:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

यदि हम उपयोग globalकरना चाहते हैं, तो यह xउचित रूप से "वैश्विक" मूल्य के लिए बाध्य होगा :

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

32
वह वैश्विक x से अलग कैसे है?
18

52
इसके समान - लेकिन ध्यान दें कि बाहरी एक्स उदाहरण में वैश्विक नहीं है, बल्कि इसके बजाय बाहरी फ़ंक्शन में परिभाषित किया गया है।
Anon

3
@ डस्टिन - वास्तव में, यदि आपके पास ए के साथ एक्स ए और सबक्लास बी में वर्ग ए है, तो आप एक्स से बी के भीतर एक्स के रूप में संदर्भित करेंगे
एनॉन

2
आंतरिक कार्यों को परिभाषित करते समय कोड आसानी से भारी हो जाता है और 79 वर्ण पीईपी 8 सिफारिश का उल्लंघन करता है। इस समस्या को हल करने का कोई तरीका? क्या किसी आंतरिक कार्य को बाहरी कार्य के बाहर रखा जा सकता है? मुझे पता है कि सवाल बेवकूफ लग रहा है, लेकिन मैं बयाना हूं।
tommy.carstensen

3
@ tommy.carstensen आप फ़ंक्शन को एक आर्ग के रूप में पारित कर सकते हैं जो उच्च आदेश कार्यों की सुंदरता है। कार्यात्मक प्रोग्रामिंग में भी इसे रचना कहा जाता है, अजगर एक शुद्ध एफपी भाषा नहीं है, लेकिन आप निश्चित रूप से एक विशेषताओं के साथ खेल सकते हैं (जनरेटर, उच्च क्रम के कार्य कुछ उदाहरण हैं)
सुपरसुरोई

90

संक्षेप में, यह आपको एक बाहरी (लेकिन गैर-वैश्विक) दायरे में एक चर के मानों को असाइन करने देता है। देखें पीईपी 3104 सभी रक्तमय जानकारी के लिए।


41

"पायथन नॉनोकॉक" के लिए एक Google खोज ने प्रस्ताव, पीईपी 3104 को बदल दिया , जो पूरी तरह से वाक्यविन्यास और कथन के पीछे तर्क का वर्णन करता है। संक्षेप में, यह globalकथन के समान ही कार्य करता है , सिवाय इसके कि इसका उपयोग उन चर को संदर्भित करने के लिए किया जाता है जो फ़ंक्शन के लिए न तो वैश्विक हैं और न ही स्थानीय हैं।

यहाँ एक संक्षिप्त उदाहरण है कि आप इसके साथ क्या कर सकते हैं। इसका उपयोग करने के लिए काउंटर जनरेटर को फिर से लिखा जा सकता है ताकि यह बंद होने के साथ भाषाओं के मुहावरों की तरह दिखे।

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

जाहिर है, आप इसे एक जनरेटर के रूप में लिख सकते हैं, जैसे:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

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


1
मुझे यकीन था कि कीवर्ड 'ग्लोबल' क्या करता है - जब तक कि यह उस नाम के साथ एक वैरिएबल तक नहीं पहुंच जाता है, तब तक उच्च वातावरण में काम करता है। वैरिएबल स्तर पर एक वैरिएबल x घोषित किया जा सकता है, एक वर्ग के अंदर, फिर इस वर्ग के अंदर एक फंक्शन में और फिर उस फंक्शन के एक इनर फंक्शन में - यह कैसे पता चलता है कि किस एक्स को संदर्भित करना है?
ooboo

7
वैश्विक के बारे में बात यह है कि यह केवल वैश्विक चर के लिए काम करता है। यह एक एन्कोडिंग, नॉनग्लोबल स्कोप में चर नहीं देख सकता है।
एकलकरण 3

मैंने मेक-एनकाउंटर की कोशिश की - हालांकि यह एक जनरेटर लेकिन एक फ़ंक्शन वापस नहीं करता है। वहाँ एक जनरेटर लौटने का एक तरीका है तो बाद में मैं उस पर पुनरावृति कर सकता हूं?
देजेल

@ डेजेल: इस उदाहरण का उद्देश्य nonlocalपाइथन में कथन का वर्णन करना है ; यदि आप प्राकृतिक संख्याओं का क्रम चाहते हैं, तो अजगर मुहावरा वास्तव में हैitertools.count()
एकलकरण संस्मरण

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

15

@ooboo:

यह स्रोत कोड में संदर्भ के बिंदु पर एक "निकटतम" लेता है। इसे "लेक्सिकल स्कोपिंग" कहा जाता है और यह 40 साल के लिए मानक है।

पायथन के वर्ग के सदस्य वास्तव में एक शब्दकोश में हैं, जिसे __dict__लेक्सिकल स्कोपिंग द्वारा कभी नहीं पहुँचा जा सकता है।

यदि आप निर्दिष्ट नहीं करते हैं nonlocalलेकिन करते हैं x = 7, तो यह एक नया स्थानीय चर "x" बनाएगा। यदि आप निर्दिष्ट करते हैं nonlocal, तो यह "निकटतम" "x" ढूंढेगा और उसी को असाइन करेगा। यदि आप निर्दिष्ट करते हैं nonlocalऔर कोई "x" नहीं है, तो यह आपको एक त्रुटि संदेश देगा।

कीवर्ड globalमुझे हमेशा अजीब लगता है क्योंकि यह सबसे बाहरी को छोड़कर अन्य सभी "x" को खुशी से अनदेखा करेगा। अजीब।


14

help ('nonlocal') nonlocalकथन


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

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

एक nonlocalबयान में सूचीबद्ध नामों के विपरीत सूचीबद्ध नामों globalको एक संलग्न दायरे में पहले से मौजूद बाइंडिंग का उल्लेख करना चाहिए (जिस दायरे में एक नया बंधन बनाया जाना चाहिए, उसे स्पष्ट रूप से निर्धारित नहीं किया जा सकता है)।

एक nonlocalबयान में सूचीबद्ध नाम स्थानीय दायरे में पहले से मौजूद बाइंडिंग से नहीं टकराते।

यह सभी देखें:

पीईपी 3104 - बाहरी स्कोप में नाम तक पहुंच बयान के
लिए विनिर्देश nonlocal

संबंधित मदद विषय: वैश्विक, NAMESPACES

स्रोत: पायथन भाषा संदर्भ


11
प्रति दिन कुछ नया सीखें। मुझे नहीं पता था कि आप help()कीवर्ड पर उपयोग कर सकते हैं (और अब मेरा दिमाग उड़ा दिया गया है: help()कोई तर्क के साथ इंटरैक्टिव नहीं होता है )।
एरिक Youngren

6

पायथन 3 संदर्भ से उद्धरण :

नॉनक्लॉक स्टेटमेंट में सूचीबद्ध पहचानकर्ताओं को ग्लोबल्स को छोड़कर निकटतम एन्कोडिंग स्कोप में पहले से बाध्य चर को संदर्भित करने का कारण बनता है।

जैसा कि संदर्भ में कहा गया है, कई नेस्टेड फ़ंक्शन के मामले में केवल निकटतम एन्कोडिंग फ़ंक्शन में परिवर्तनशील है:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

"निकटतम" चर कई स्तरों दूर हो सकता है:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

लेकिन यह एक वैश्विक चर नहीं हो सकता है:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found

3
a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)

2

"नॉनक्लॉक" स्टेटमेंट के बारे में मेरी व्यक्तिगत समझ (और मुझे क्षमा करें क्योंकि मैं सामान्य रूप से पायथन और प्रोग्रामिंग के लिए नया हूं) यह है कि "नॉनक्लॉक" कोड के मुख्य भाग के बजाय पुनरावृत्त कार्यों के भीतर वैश्विक कार्यक्षमता का उपयोग करने का एक तरीका है। । यदि आप करेंगे कार्यों के बीच एक वैश्विक बयान।


0

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

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.