গ্লোবাল (), স্থানীয় () এবং ভারস () এর মধ্যে পার্থক্য কী?


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, আমরা একটি রিটার্ন মান সংরক্ষণ না করেও একটি এন্ট্রি দেখায় । তৃতীয় এবং চতুর্থ printএর দেখায় যে ভেরিয়েবলগুলি নির্ধারণ করা আপডেট হয় না lএবং বিপরীত হয় না , তবে আমরা অ্যাক্সেস করার পরে f_localsস্থানীয় ভেরিয়েবলগুলি locals()আবার অনুলিপি করা হয়।

দুটি নোট:

  1. এই আচরণটি সিপথন নির্দিষ্ট - অন্যান্য পাইথনস আপডেটগুলি স্বয়ংক্রিয়ভাবে স্থানীয় নেমস্পেসে ফিরে আসতে পারে allow
  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
অংশটি "এবং অভিধানের কোনও অ্যাসাইনমেন্ট প্রকৃত স্থানীয় নেমস্পেসে প্রতিফলিত হয় না" নির্দিষ্ট করে কিছুটা বলা যেতে পারে ।
সোভেন মারনাচ

আশ্চর্যের ব্যাপার, আপনি একটি TO- এ যুক্ত ভেরিয়েবল অ্যাক্সেস করতে পারেন vars()অথবা locals()অভিধান যদি আপনি ব্যবহার একটি ফাংশন মধ্যে নামক eval()। EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')প্রিন্ট 4 test()কার্যকর করা হয় যখন !
মার্ক মিকোফস্কি

1
প্রকৃতপক্ষে অ্যাসাইনমেন্টটি dict(ফিরে locals()) স্থানীয় নেমস্পেসে প্রতিফলিত হয় এবং স্থানীয় নেমস্পেসে পরিবর্তনগুলি dict(আমার অজগরটিতে) প্রতিফলিত হতে দেখা যায় । একমাত্র জিনিস স্পেসিফিকেশন এই আচরণের গ্যারান্টি দেয় না।
আকাশ ছোঁয়াচ্ছে

টার্ম নাম সুযোগ ব্যবহার তুলনায় আমার জীবন আরও অনেক সহজ মনে হচ্ছে নামস্থান
ওভাররেচেন্জ করুন

1
@ সার্বভৌম এক্সচেঞ্জ: import thisএবং গুগলেsite:docs.python.org namespace
ইথান ফুরম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.