सवाल फ़ंक्शन में वैश्विक चर का उपयोग करना


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

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


2478
2018-01-08 05:45


मूल




जवाब:


आप इसे घोषित करके अन्य कार्यों में वैश्विक चर का उपयोग कर सकते हैं global प्रत्येक कार्य में जो इसे असाइन करता है:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

मुझे कल्पना है कि इसका कारण यह है कि, चूंकि वैश्विक चर इतने खतरनाक हैं, इसलिए पाइथन यह सुनिश्चित करना चाहता है कि आप वास्तव में जानते हैं कि आप जो कुछ भी खेल रहे हैं उसे स्पष्ट रूप से आवश्यक है global कीवर्ड।

यदि आप मॉड्यूल में ग्लोबल वैरिएबल साझा करना चाहते हैं तो अन्य उत्तरों देखें।


3509
2018-01-08 08:39



ग्लोबल्स को "इतना खतरनाक" के रूप में संदर्भित करना बेहद असाधारण है। Globals हर भाषा में पूरी तरह से ठीक है जो कभी अस्तित्व में है और कभी अस्तित्व में होगा। उनके पास जगह है। आपको क्या कहना चाहिए था कि यदि आपके पास कोई संकेत नहीं है कि प्रोग्राम कैसे करें, तो वे समस्याएं पैदा कर सकते हैं। - Anthony
मुझे लगता है कि वे काफी खतरनाक हैं। हालांकि पाइथन में "वैश्विक" चर वास्तव में मॉड्यूल-स्तर हैं, जो कई मुद्दों को हल करता है। - Fábio Santos
मैं असहमत हूं कि पाइथन के कारण की आवश्यकता है global कीवर्ड इसलिए है क्योंकि ग्लोबल्स खतरनाक हैं। इसके बजाए, ऐसा इसलिए है क्योंकि भाषा को आपको स्पष्ट रूप से चर घोषित करने की आवश्यकता नहीं होती है और स्वचालित रूप से मान ली जाती है कि आपके द्वारा असाइन किए गए एक चर के पास कार्यक्षेत्र है जब तक कि आप इसे अन्यथा नहीं बताते। global कीवर्ड वह माध्यम है जो इसे अन्यथा बताने के लिए प्रदान किया जाता है। - Nate C-K
वैश्विक चर एक डिजाइन गंध है, लगभग हर भाषा में मैंने व्यावसायिक रूप से उपयोग किया है। मान लें कि आपके पास एक फ़ंक्शन है जो तीन बूलियन लेता है: यह जांचने के लिए 8 संभावित कोड पथ हैं। यदि आपके पास बूलियन तर्कों की संख्या के साथ 3 फ़ंक्शन हैं, तो यह 24 संभावित कोड पथ हैं। फिर एक एकल बूलियन ग्लोबल वैरिएबल जोड़ें, अब आप 24 ^ 2 संभावित कोड पथ देख रहे हैं क्योंकि आपको इस तथ्य के लिए जिम्मेदार होना है कि सभी कार्यों में उस वैश्विक चर की स्थिति को बदलने की क्षमता है। यही कारण है कि कार्यात्मक प्रोग्रामिंग तकनीक लोकप्रिय हो गई है। - avgvstvs
@LightnessRacesinOrbit मुझे आपका अंक नहीं मिल रहा है। यदि आप वैश्विक चर को हटाते हैं, तो आप उस समय जटिल कारक को हटा देते हैं, मनमानी कार्य अब प्रोग्राम स्थिति को बदल नहीं सकते हैं, निष्पादन में विभिन्न बिंदुओं पर - इस प्रकार निष्पादन को ऐसे तरीके से बदलना जो अन्यथा उन चर पर निर्भर अन्य कार्यों के लिए अतिसंवेदनशील है। अब आपको ट्रैक रखना नहीं है, "क्या f2() अब राज्य बदलें f3() कुछ अप्रत्याशित कर सकता है? कार्य अब बाहरी कार्यक्रम राज्य के लिए अज्ञेयवादी संचालित कर सकते हैं। - avgvstvs


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

मान लें कि आपके पास एक मॉड्यूल है:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

आप इसे 42 प्रिंट करने की उम्मीद कर सकते हैं, लेकिन इसके बजाय यह प्रिंट करता है 5. जैसा कि पहले से ही उल्लेख किया गया है, यदि आप 'global'घोषणा func1(), फिर func2() 42 प्रिंट करेगा।

def func1():
    global myGlobal
    myGlobal = 42

यहां क्या हो रहा है कि पाइथन मानता है कि कोई भी नाम है को सौंपना, किसी भी फ़ंक्शन के भीतर, उस फ़ंक्शन के लिए स्थानीय है जब तक कि स्पष्ट रूप से अन्यथा नहीं बताया जाता। अगर यह केवल है पढ़ना किसी नाम से, और नाम स्थानीय रूप से मौजूद नहीं है, यह किसी भी स्कॉप्स (जैसे मॉड्यूल का वैश्विक दायरा) में नाम देखने की कोशिश करेगा।

जब आप नाम पर 42 असाइन करते हैं myGlobalइसलिए, पायथन एक स्थानीय चर बनाता है जो एक ही नाम के वैश्विक चर को छाया करता है। वह स्थानीय दायरे से बाहर चला जाता है और है कचरा-एकत्र कब func1() रिटर्न; इस दौरान, func2() (अनमोडिफाइड) वैश्विक नाम के अलावा कुछ भी नहीं देख सकता है। ध्यान दें कि यह नेमस्पेस निर्णय संकलन समय पर होता है, रनटाइम पर नहीं - यदि आप का मान पढ़ना चाहते हैं myGlobal के भीतर func1() इससे पहले कि आप इसे आवंटित करें, आपको एक मिल जाएगा UnboundLocalError, क्योंकि पाइथन ने पहले ही फैसला कर लिया है कि यह एक स्थानीय चर होना चाहिए लेकिन इसके साथ अभी तक कोई मूल्य नहीं है। लेकिन 'global'कथन, आप पाइथन को बताते हैं कि इसे स्थानीय रूप से असाइन करने के बजाय इसे नाम के लिए कहीं और देखना चाहिए।

(मेरा मानना ​​है कि यह व्यवहार स्थानीय नामस्थानों के अनुकूलन के माध्यम से बड़े पैमाने पर उत्पन्न हुआ - इस व्यवहार के बिना, पाइथन के वीएम को प्रत्येक समारोह में किसी नए नाम को आवंटित करने के लिए कम से कम तीन नाम लुकअप करने की आवश्यकता होगी (यह सुनिश्चित करने के लिए कि नाम नहीं किया गया है ' टी मॉड्यूल / बिल्टिन स्तर पर पहले से मौजूद है), जो काफी आम ऑपरेशन को धीमा कर देगा।)


661
2018-01-08 09:19



आपने बताया कि नामस्थान निर्णय होता है समय संकलित करें, मुझे नहीं लगता कि यह सच है। जो मैं पाइथन संकलन सीखता हूं उससे सिंटैक्स त्रुटि के लिए केवल जांच करता है, नाम त्रुटि नहीं इस उदाहरण का प्रयास करें डीएफ ए (): एक्स + = 1, यदि आप इसे नहीं चलाते हैं, तो यह होगा UnboundLocalError मत देनाकृपया धन्यवाद, धन्यवाद - watashiSHUN
वैश्विक चर के लिए पूंजी पत्र का उपयोग करना आम बात है MyGlobal = 5 - Vassilis
@ वाताशीशुन: नामस्थान निर्णय कर देता है संकलन समय पर होता है। यह तय करना x स्थानीय समय रनटाइम पर जांच से अलग है यदि स्थानीय नाम पहली बार इस्तेमाल होने से पहले किसी मान से जुड़ा हुआ था। - BlackJack
@ वासिलिस: यह ऊपरी मामले के लिए आम है सब पत्र: MY_GLOBAL = 5। देखें पायथन कोड के लिए स्टाइल गाइड। - BlackJack
@ ब्लैक जैक, हाँ आदमी, तुम सही हो! (मैं सी के लिए उपयोग किया जाता है) - Vassilis


आप की धारणा का पता लगाना चाह सकते हैं नामस्थान। पायथन में, मॉड्यूल के लिए प्राकृतिक जगह है वैश्विक डेटा:

प्रत्येक मॉड्यूल की अपनी निजी प्रतीक तालिका होती है, जिसे मॉड्यूल में परिभाषित सभी कार्यों द्वारा वैश्विक प्रतीक तालिका के रूप में उपयोग किया जाता है। इस प्रकार, मॉड्यूल के लेखक उपयोगकर्ता के वैश्विक चर के साथ आकस्मिक संघर्षों के बारे में चिंता किए बिना मॉड्यूल में वैश्विक चर का उपयोग कर सकते हैं। दूसरी तरफ, यदि आप जानते हैं कि आप क्या कर रहे हैं तो आप एक मॉड्यूल के ग्लोबल वैरिएबल को उसी फ़ंक्शन के साथ स्पर्श कर सकते हैं जो इसके कार्यों को संदर्भित करता है, modname.itemname

ग्लोबल-इन-ए-मॉड्यूल का एक विशिष्ट उपयोग यहां वर्णित है - कैसे करते हैं-ए-शेयर वैश्विक चर-भर-मॉड्यूल, और पूर्णता के लिए सामग्री यहां साझा की जाती है:

एक प्रोग्राम के भीतर मॉड्यूल में जानकारी साझा करने का कैननिकल तरीका एक विशेष कॉन्फ़िगरेशन मॉड्यूल (अक्सर कॉन्फ़िगर या सीएफजी कहा जाता है) बनाना है। बस अपने आवेदन के सभी मॉड्यूल में कॉन्फ़िगरेशन मॉड्यूल आयात करें; मॉड्यूल फिर वैश्विक नाम के रूप में उपलब्ध हो जाता है। क्योंकि प्रत्येक मॉड्यूल का केवल एक उदाहरण है, मॉड्यूल ऑब्जेक्ट में किए गए कोई भी परिवर्तन हर जगह परिलक्षित होते हैं। उदाहरण के लिए:

फ़ाइल: config.py

x = 0   # Default value of the 'x' configuration setting

फ़ाइल: mod.py

import config
config.x = 1

फ़ाइल: main.py

import config
import mod
print config.x

175
2018-01-08 05:59



एक कारण के लिए मुझे पसंद नहीं है config.x  क्या मैं इससे छुटकारा पा सकता हूं? मैं साथ आया x = lambda: config.x और फिर मेरे पास है नया में मूल्य x()। किसी कारण से, होने a = config.x मेरे लिए चाल नहीं करता है। - vladosaurus


पाइथन स्थानीय और वैश्विक के बीच, एक चर को लोड करने के लिए कौन सा दायरा तय करना है, यह तय करने के लिए एक सरल ह्युरिस्टिक का उपयोग करता है। यदि एक असाइनमेंट के बाईं ओर एक चर नाम दिखाई देता है, लेकिन वैश्विक घोषित नहीं किया जाता है, तो यह स्थानीय माना जाता है। यदि यह किसी असाइनमेंट के बाईं ओर दिखाई नहीं देता है, तो इसे वैश्विक माना जाता है।

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>> 

देखें कि कैसे एक बाज, जो एक असाइनमेंट के बाईं तरफ दिखाई देता है foo(), सिर्फ यही LOAD_FAST चर।


75
2017-07-12 12:35



ह्युरिस्टिक दिखता है बाध्यकारी परिचालन। असाइनमेंट एक ऐसा ऑपरेशन है, जो दूसरे को आयात करता है। लेकिन एक का लक्ष्य for लूप और नाम के बाद as में with तथा except बयान भी बाध्य हैं। - Martijn Pieters♦


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

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

इसके अलावा, वैश्विक चर उपयोगी हैं, कुछ ओओपी zealots के विपरीत जो अन्यथा दावा करते हैं - खासकर छोटी लिपियों के लिए, जहां ओओपी अधिक है।


48
2018-01-08 09:03





पहले से ही मौजूदा उत्तरों के अलावा और इसे और अधिक भ्रमित करने के लिए:

पायथन में, चर जो केवल फ़ंक्शन के अंदर संदर्भित होते हैं    पूरी तरह से वैश्विक। यदि एक चर को कहीं भी एक नया मान सौंपा गया है   समारोह के शरीर के भीतर, यह एक माना जाता है स्थानीय। यदि एक चर   फ़ंक्शन के अंदर कभी भी एक नया मान असाइन किया गया है, चर है   निस्संदेह स्थानीय, और आपको स्पष्ट रूप से इसे 'वैश्विक' घोषित करने की आवश्यकता है।

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

स्रोत: पायथन में स्थानीय और वैश्विक चर के नियम क्या हैं?


36
2017-07-04 10:23





यदि मैं एक फ़ंक्शन में वैश्विक चर बना देता हूं, तो मैं उस चर को किसी अन्य फ़ंक्शन में कैसे उपयोग कर सकता हूं?

हम निम्नलिखित फ़ंक्शन के साथ वैश्विक बना सकते हैं:

def create_global_variable():
    global global_variable # must declare it to be a global first
    # modifications are thus reflected on the module's global scope
    global_variable = 'Foo' 

एक फ़ंक्शन लिखना वास्तव में अपना कोड नहीं चलाता है। तो हम कहते हैं create_global_variable समारोह:

>>> create_global_variable()

संशोधन के बिना globals का उपयोग करना

आप इसका उपयोग केवल तब कर सकते हैं, जब तक आप यह बदलने की अपेक्षा न करें कि यह किस वस्तु को इंगित करता है:

उदाहरण के लिए,

def use_global_variable():
    return global_variable + '!!!'

और अब हम वैश्विक चर का उपयोग कर सकते हैं:

>>> use_global_variable()
'Foo!!!'

एक समारोह के अंदर से वैश्विक चर का संशोधन

वैश्विक चर को किसी भिन्न ऑब्जेक्ट पर इंगित करने के लिए, आपको फिर से वैश्विक कीवर्ड का उपयोग करना होगा:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

ध्यान दें कि इस फ़ंक्शन को लिखने के बाद, कोड वास्तव में इसे बदल रहा है अभी भी नहीं चला है:

>>> use_global_variable()
'Foo!!!'

तो समारोह को कॉल करने के बाद:

>>> change_global_variable()

हम देख सकते हैं कि वैश्विक चर बदल दिया गया है। global_variable नाम अब इंगित करता है 'Bar':

>>> use_global_variable()
'Bar!!!'

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

एक ही नाम के साथ स्थानीय चर

यदि आप एक ही नाम के साथ एक स्थानीय चर बनाते हैं, तो यह एक वैश्विक चर को ढंक देगा:

def use_local_with_same_name_as_global():
    # bad name for a local variable, though.
    global_variable = 'Baz' 
    return global_variable + '!!!'

>>> use_local_with_same_name_as_global()
'Baz!!!'

लेकिन उस गलत नामित स्थानीय चर का उपयोग करके वैश्विक चर बदलता नहीं है:

>>> use_global_variable()
'Bar!!!'

ध्यान दें कि आपको ग्लोबल्स के समान नामों के साथ स्थानीय चर का उपयोग करने से बचना चाहिए जबतक कि आप ठीक से नहीं जानते कि आप क्या कर रहे हैं और ऐसा करने का बहुत अच्छा कारण है। मुझे अभी तक ऐसा कोई कारण नहीं मिला है।


31
2018-01-01 19:55





समांतर निष्पादन के साथ, यदि आप समझ में नहीं आ रहे हैं कि क्या हो रहा है तो वैश्विक चर अप्रत्याशित परिणाम दे सकते हैं। मल्टीप्रोसेसिंग के भीतर एक वैश्विक चर का उपयोग करने का एक उदाहरण यहां दिया गया है। हम स्पष्ट रूप से देख सकते हैं कि प्रत्येक प्रक्रिया चर की अपनी प्रति के साथ काम करती है:

import multiprocessing
import os
import random
import sys
import time

def worker(new_value):
    old_value = get_value()
    set_value(random.randint(1, 99))
    print('pid=[{pid}] '
          'old_value=[{old_value:2}] '
          'new_value=[{new_value:2}] '
          'get_value=[{get_value:2}]'.format(
          pid=str(os.getpid()),
          old_value=old_value,
          new_value=new_value,
          get_value=get_value()))

def get_value():
    global global_variable
    return global_variable

def set_value(new_value):
    global global_variable
    global_variable = new_value

global_variable = -1

print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after  set_value(), get_value() = [%s]' % get_value())

processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))

आउटपुट:

before set_value(), get_value() = [-1]
after  set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]

28
2017-10-03 05:41





आप जिस फ़ंक्शन का उपयोग करना चाहते हैं उसमें वैश्विक चर को संदर्भित करने की आवश्यकता है।

निम्नलिखित नुसार:

var = "test"

def printGlobalText():
    global var #wWe are telling to explicitly use the global version
    var = "global from printGlobalText fun."
    print "var from printGlobalText: " + var

def printLocalText():
    #We are NOT telling to explicitly use the global version, so we are creating a local variable
    var = "local version from printLocalText fun"
    print "var from printLocalText: " + var

printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""

19
2017-12-20 12:45



'आप जिस फ़ंक्शन का उपयोग करना चाहते हैं' में संक्षेप में गलत है, इसके करीब होना चाहिए: 'हर फ़ंक्शन में जहां आप चाहते हैं अद्यतन करें' - spazm