ग्लोबल्स (), लोकल (), और vars () में क्या अंतर है?


146

बीच क्या अंतर है globals(), locals()और vars()? वे क्या लौटाते हैं? क्या परिणामों के अपडेट उपयोगी हैं?


क्या अजगर 3 में से किसी को भी अपडेट कर सकता है और क्या स्क्रिप्ट वास्तव में काम करती है?
चार्ली पार्कर

जवाबों:


172

इनमें से प्रत्येक एक शब्दकोश लौटाते हैं:

  • globals() हमेशा मॉड्यूल नेमस्पेस का शब्दकोश लौटाता है
  • locals() हमेशा वर्तमान नामस्थान का एक शब्दकोश देता है
  • vars()रिटर्न या तो एक वर्तमान नाम स्थान (यदि कोई तर्क के साथ कॉल) या शब्दकोश तर्क के शब्दकोश।

localsऔर varsकुछ और स्पष्टीकरण का उपयोग कर सकता है। यदि locals()इसे किसी फ़ंक्शन के अंदर कहा जाता है, तो यह उस क्षण के रूप में वर्तमान स्थानीय चर नामस्थान (प्लस किसी भी क्लोजर चर) के मूल्यों के साथ एक तानाशाही को अद्यतन करता है और इसे वापस करता है। एक locals()ही स्टैक फ्रेम में एकाधिक कॉल हर बार एक ही तरह से वापस आती हैं - यह स्टैक फ्रेम ऑब्जेक्ट से इसकी f_localsविशेषता के रूप में जुड़ा हुआ है । प्रत्येक locals()कॉल और प्रत्येक f_localsविशेषता एक्सेस पर तानाशाह की सामग्री अपडेट की जाती है , लेकिन केवल ऐसे कॉल या विशेषता एक्सेस पर। जब चर असाइन किए जाते हैं, तो यह स्वचालित रूप से अपडेट नहीं होता है, और हुक में प्रविष्टियों को असाइन करना संबंधित स्थानीय चर को असाइन नहीं करेगा:

import inspect

def f():
    x = 1
    l = locals()
    print(l)
    locals()
    print(l)
    x = 2
    print(x, l['x'])
    l['x'] = 3
    print(x, l['x'])
    inspect.currentframe().f_locals
    print(x, l['x'])

f()

हमें देता है:

{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2

पहला print(l)केवल एक 'x'प्रविष्टि दिखाता है , क्योंकि असाइनमेंट कॉल के lबाद होता है locals()। दूसरा print(l), locals()फिर से कॉल करने के बाद , एक lप्रविष्टि दिखाता है , भले ही हमने रिटर्न वैल्यू को नहीं बचाया है। तीसरे और चौथे prints शो में बताया गया है कि वेरिएबल्स को असाइन करना अपडेट नहीं है lऔर इसके विपरीत, लेकिन हम एक्सेस करने के बाद f_locals, स्थानीय वेरिएबल्स को locals()फिर से कॉपी किया जाता है।

दो नोट:

  1. यह व्यवहार CPython विशिष्ट है - अन्य पायथन अपडेट को स्थानीय नामस्थान पर स्वचालित रूप से वापस करने की अनुमति दे सकते हैं।
  2. सीपीथॉन 2.x exec "pass"में फ़ंक्शन में एक लाइन डालकर इस काम को करना संभव है । यह फ़ंक्शन को पुराने, धीमे निष्पादन मोड में स्विच करता है जो locals()स्थानीय चर के विहित प्रतिनिधित्व के रूप में तानाशाह का उपयोग करता है ।

यदि इसे किसी फ़ंक्शन के बाहरlocals() कहा जाता है तो यह वास्तविक शब्दकोश देता है जो वर्तमान नामस्थान है। नाम स्थान के लिए आगे के परिवर्तन कर रहे हैं शब्दकोश में परिलक्षित होता है, और शब्दकोश में परिवर्तन कर रहे हैं नाम स्थान में परिलक्षित:

class Test(object):
    a = 'one'
    b = 'two'
    huh = locals()
    c = 'three'
    huh['d'] = 'four'
    print huh

हमें देता है:

{
  'a': 'one',
  'b': 'two',
  'c': 'three',
  'd': 'four',
  'huh': {...},
  '__module__': '__main__',
}

अब तक, मैंने जो कुछ locals()भी कहा है, उसके लिए भी सही है vars()... यहाँ अंतर है: vars()किसी एक वस्तु को उसके तर्क के रूप में स्वीकार करता है, और यदि आप इसे एक वस्तु देते हैं तो यह __dict__उस वस्तु का लाभ देता है । किसी विशिष्ट ऑब्जेक्ट के लिए, यह __dict__वह जगह है जहां इसका अधिकांश विशेषता डेटा संग्रहीत होता है। इसमें वर्ग चर और मॉड्यूल ग्लोबल्स शामिल हैं:

class Test(object):
    a = 'one'
    b = 'two'
    def frobber(self):
        print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()

जो हमें देता है:

three

ध्यान दें कि एक फ़ंक्शन का __dict__विशेषता नाम स्थान है, न कि स्थानीय चर। यह __dict__स्थानीय चर को संचय करने के लिए एक समारोह के लिए कोई मतलब नहीं होगा , क्योंकि पुनरावृत्ति और बहुतायत का मतलब एक ही समय में एक समारोह में कई कॉल हो सकते हैं, प्रत्येक अपने स्थानीय लोगों के साथ:

def f(outer):
    if outer:
        f(False)
        print('Outer call locals:', locals())
        print('f.__dict__:', f.__dict__)
    else:
        print('Inner call locals:', locals())
        print('f.__dict__:', f.__dict__)

f.x = 3

f(True)

जो हमें देता है:

Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}

यहां, fखुद को पुनरावर्ती कहता है, इसलिए आंतरिक और बाहरी कॉल ओवरलैप होते हैं। जब यह कॉल करता है locals(), तो प्रत्येक अपना स्वयं का स्थानीय चर देखता है , लेकिन दोनों कॉल समान दिखते हैं f.__dict__, और f.__dict__इसमें कोई स्थानीय चर नहीं है।


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

विचित्र रूप से पर्याप्त है, यदि आप उपयोग करते हैं, तो किसी फ़ंक्शन में जोड़े गए शब्दकोश vars()या locals()शब्दकोश में एक्सेस किए गए चर का उपयोग कर सकते हैं eval()। उदा: निष्पादित def test(): huh = locals(); huh['d'] = 4; print eval('d')होने पर 4 प्रिंट करता test()है!
मार्क मिकोस्की

1
वास्तव में dict(द्वारा लौटाया गया locals()) असाइनमेंट स्थानीय नामस्थान में परिलक्षित होता है और स्थानीय नामस्थान में परिवर्तन dict(मेरे अजगर में) परिलक्षित होता है । केवल एक चीज यह है कि विनिर्देश इस व्यवहार की गारंटी नहीं देता है।
skyking

नेमस्पेस की तुलना में टर्म नेम स्कोप का उपयोग मेरे लिए अधिक आसान लगता है ।
ओवरएक्सचेंज

1
@overexchange: import thisऔर google मेंsite:docs.python.org namespace
Ethan Furman
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.