একটি ফাংশনে গ্লোবাল ভেরিয়েবল ব্যবহার করা


3112

আমি কীভাবে কোনও ফাংশনে একটি বৈশ্বিক পরিবর্তনশীল তৈরি বা ব্যবহার করতে পারি?

যদি আমি একটি ফাংশনে একটি বৈশ্বিক পরিবর্তনশীল তৈরি করি, তবে আমি কীভাবে অন্য ফাংশনে সেই বৈশ্বিক চলকটি ব্যবহার করতে পারি? আমার কি অ্যাক্সেসের প্রয়োজন ফাংশনটির স্থানীয় ভেরিয়েবলে গ্লোবাল ভেরিয়েবল সংরক্ষণ করতে হবে?

উত্তর:


4242

আপনি এটি 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শব্দটি স্পষ্টভাবে কীওয়ার্ডের প্রয়োজনের দ্বারা খেলছেন know

আপনি যদি মডিউলগুলিতে একটি বৈশ্বিক পরিবর্তনশীল ভাগ করতে চান তবে অন্যান্য উত্তরগুলি দেখুন।


838
গ্লোবালগুলিকে "এত বিপজ্জনক" হিসাবে উল্লেখ করা চরম অতিরঞ্জিত। গ্লোবালগুলি প্রতিটি ভাষারই পুরোপুরি সূক্ষ্ম ever তাদের জায়গা আছে। আপনার যা বলা উচিত ছিল তা হ'ল যদি আপনার কীভাবে প্রোগ্রাম করবেন তার কোনও ক্লু না থাকলে তারা সমস্যার সৃষ্টি করতে পারে।
অ্যান্টনি

207
আমি মনে করি এগুলি মোটামুটি বিপজ্জনক। তবে পাইথনে "গ্লোবাল" ভেরিয়েবলগুলি আসলে মডিউল স্তরের যা অনেকগুলি সমস্যার সমাধান করে।
ফেবিও সান্টোস

246
আমি একমত নই যে পাইথনের globalকীওয়ার্ডটির প্রয়োজনের কারণ হ'ল গ্লোবালগুলি বিপজ্জনক। এর পরিবর্তে, কারণ ভাষার স্পষ্টরূপে ভেরিয়েবলগুলি ঘোষণা করার প্রয়োজন নেই এবং স্বয়ংক্রিয়ভাবে ধরে নেওয়া হয় যে আপনি যে ভেরিয়েবলটি বরাদ্দ করেছেন তার ফাংশনের সুযোগ রয়েছে অন্যথায় না বললে। মূল globalশব্দটি হ'ল উপায় যা অন্যথায় এটি বলার জন্য সরবরাহ করা হয়।
Nate CK

7
@avgvstvs: এবং যদি আপনি গ্লোবাল ছাড়াই একই প্রোগ্রামটি বাস্তবায়ন করেন তবে আপনার কাছে এখনও একই সংখ্যার কোড পাথ রয়েছে। আপনি যে যুক্তিটি করেছেন তা গ্লোবালের বিরুদ্ধে নয়।
bit

13
পছন্দ করুন আপনি যদি কোনও বৈশ্বিক চলক অপসারণ করেন, আপনি এখন সেই জটিল বিষয়টিকে সরিয়ে ফেলেন, নির্বিচারে ফাংশনগুলি কার্যকরভাবে প্রয়োগের বিভিন্ন পয়েন্টে আর প্রোগ্রামের স্থিতি পরিবর্তন করতে পারে না - এইভাবে কার্যকরভাবে এমনভাবে পরিবর্তন করা হয় যা অন্যথায় সেই ভেরিয়েবলের উপর নির্ভরশীল অন্যান্য ক্রিয়াকলাপগুলির জন্য অবর্ণনীয়। আপনাকে আর ট্র্যাক রাখতে হবে না, " f2()রাষ্ট্রের পরিবর্তনের ফলে এখন f3()কি অপ্রত্যাশিত কিছু হতে পারে? ফাংশনগুলি এখন বাহ্যিক প্রোগ্রামের রাজ্যে অজ্ঞেয়বাদী পরিচালনা করতে পারে
avgvstvs

775

যদি আমি আপনার পরিস্থিতিটি সঠিকভাবে বুঝতে পারি তবে আপনি যা দেখছেন তা পাইথন কীভাবে স্থানীয় (ফাংশন) এবং বিশ্বব্যাপী (মডিউল) নেমস্পেসগুলি পরিচালনা করে।

বলুন যে আপনি এর মতো একটি মডিউল পেয়েছেন:

# 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' স্টেটমেন্টটি ব্যবহার করে আপনি পাইথনকে বলেছিলেন যে এটি স্থানীয়ভাবে নির্ধারণের পরিবর্তে নামের জন্য এটি অন্য কোথাও দেখতে হবে।

(আমি বিশ্বাস করি যে স্থানীয় নেমস্পেসগুলির অপ্টিমাইজেশনের মাধ্যমে এই আচরণটি মূলত উত্সাহিত হয়েছিল - এই আচরণ ব্যতীত পাইথনের ভিএম-এর প্রতিটি সময় কোনও ফাংশনের অভ্যন্তরে নতুন নাম নির্ধারিত হওয়ার পরে কমপক্ষে তিনটি নাম অনুসন্ধান করতে হবে (নামটি নিশ্চিত হয়নি তা নিশ্চিত করার জন্য) টি ইতিমধ্যে মডিউল / বিল্টিন স্তরে উপস্থিত রয়েছে), যা খুব সাধারণ ক্রিয়াকলাপটিকে উল্লেখযোগ্যভাবে কমিয়ে দেবে))


আপনি উল্লেখ করেছিলেন যে সংকলনের সময় নেমস্পেসের সিদ্ধান্ত হয় , আমি এটি সত্য বলে মনে করি না। পাইথনের সংকলনটি আমি যা শিখেছি তা থেকে কেবল সিনট্যাক্স ত্রুটির জন্য পরীক্ষা করা হয়, নাম ত্রুটি নয় উদাহরণস্বরূপ এএফ (): x + = 1 , যদি আপনি এটি চালনা না করেন তবে এটি আনবাউন্ডলোক্যালআরার দেয় না , দয়া করে আপনাকে যাচাই করুন ধন্যবাদ
ওয়াটাশিউন

1
গ্লোবাল ভেরিয়েবলের জন্য বড় হাতের অক্ষর ব্যবহার করা সাধারণMyGlobal = 5
ভ্যাসিলিস

3
@ওয়াতাসি শুন: সংকলনের সময় নেমস্পেসের সিদ্ধান্ত হয়xস্থানীয় যে স্থানীয় তা সিদ্ধান্ত নেওয়ার সময় রানটাইম পরীক্ষা করা থেকে আলাদা যদি স্থানীয় নামটি প্রথমবার ব্যবহারের আগে কোনও মানের সাথে আবদ্ধ থাকে।
ব্ল্যাকজ্যাক

9
@Vassilis: এটা উপরের ক্ষেত্রে সাধারণ সব চিঠি: MY_GLOBAL = 5পাইথন কোডের জন্য স্টাইল গাইড দেখুন ।
ব্ল্যাকজ্যাক

223

আপনি নেমস্পেসের ধারণাটি অন্বেষণ করতে চাইতে পারেন । পাইথনে, মডিউলটি বিশ্বব্যাপী ডেটার জন্য প্রাকৃতিক জায়গা :

প্রতিটি মডিউলের নিজস্ব ব্যক্তিগত প্রতীক টেবিল থাকে যা মডিউলটিতে সংজ্ঞায়িত সমস্ত ফাংশন দ্বারা বৈশ্বিক প্রতীক টেবিল হিসাবে ব্যবহৃত হয়। সুতরাং, কোনও মডিউলটির লেখক কোনও ব্যবহারকারীর বৈশ্বিক ভেরিয়েবলগুলির সাথে দুর্ঘটনাজনিত সংঘর্ষের বিষয়ে চিন্তা না করে মডিউলটিতে গ্লোবাল ভেরিয়েবলগুলি ব্যবহার করতে পারেন। অন্যদিকে, আপনি যদি জানেন যে আপনি কী করছেন আপনি কোনও মডিউলের গ্লোবাল ভেরিয়েবলগুলিকে একই ফাংশনটি উল্লেখ করতে ব্যবহার করতে পারেন modname.itemname,।

গ্লোবাল-ইন-এ-অ-মডিউলটির একটি নির্দিষ্ট ব্যবহার এখানে বর্ণিত হয়েছে - আমি মডিউলগুলিতে কীভাবে বৈশ্বিক চলকগুলি ভাগ করব? , এবং সম্পূর্ণতার জন্য বিষয়বস্তু এখানে ভাগ করা হয়:

একটি একক প্রোগ্রামের মধ্যে মডিউল জুড়ে তথ্য ভাগ ক্যানোনিকাল পথ একটি বিশেষ কনফিগারেশন মডিউল (প্রায়ই বলা তৈরি করা কনফিগ বা cfg )। আপনার অ্যাপ্লিকেশনটির সমস্ত মডিউলগুলিতে কনফিগারেশন মডিউলটি কেবল আমদানি করুন; মডিউলটি তখন একটি বিশ্বব্যাপী নাম হিসাবে উপলব্ধ হয়। যেহেতু প্রতিটি মডিউলের কেবল একটি উদাহরণ রয়েছে, মডিউল অবজেক্টে করা যেকোনো পরিবর্তন সর্বত্র প্রতিবিম্বিত হয়। উদাহরণ স্বরূপ:

ফাইল: 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

1
একটি কারণে আমি ক্যানটি পছন্দ করি না config.x এটি থেকে মুক্তি পেতে পারি? আমি সাথে এসেছিলাম x = lambda: config.xএবং তারপরে আমার নতুন মান রয়েছে x()। কিছু কারণে, a = config.xআমার জন্য কৌশলটি করে না।
ভ্লাদোসরাস

3
@ ভ্লাদোসরাস কি from config import xসমাধান করে?
ঝিল্যান্ডস

93

পাইথন স্থানীয় এবং বৈশ্বিকের মধ্যে কোন স্কের থেকে কোনও পরিবর্তনশীল লোড করা উচিত তা সিদ্ধান্ত নিতে একটি সাধারণ হিউরিস্টিক ব্যবহার করে। যদি কোনও চলকের নাম কোনও অ্যাসাইনমেন্টের বাম দিকে উপস্থিত হয়, তবে এটি বিশ্বব্যাপী ঘোষিত না হয়, তবে এটি স্থানীয় বলে ধরে নেওয়া হয়। যদি এটি কোনও অ্যাসাইনমেন্টের বাম দিকে উপস্থিত না হয়, তবে এটি বিশ্বব্যাপী বলে ধরে নেওয়া হয়।

>>> 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চলক হয় তা দেখুন।


12
বাধ্যতামূলক অপারেশনগুলির জন্য হিউরিস্টিক দেখায় । অ্যাসাইনমেন্ট এমন একটি অপারেশন, অন্যটি আমদানি করে। কিন্তু একজন লক্ষ্য forলুপ এবং পরে নাম asমধ্যে withএবং exceptবিবৃতি এছাড়াও আবদ্ধ হয়।
মার্টিজন পিটারস

পরে @MartijnPieters নাম জন্য asএকটি ইন exceptদফা এটা আমার সুস্পষ্ট ছিল না। তবে এটি স্মৃতি সংরক্ষণ করতে স্বয়ংক্রিয়ভাবে মুছে ফেলা হয়।
রবার্ট

1
@ রবার্ট: স্মৃতি সংরক্ষণ করতে নয়, তবে একটি বিজ্ঞপ্তি রেফারেন্স তৈরি করা এড়ানোর জন্য যা স্মৃতি ফাঁস হতে পারে। কারণ ব্যতিক্রম একটি ট্রেসব্যাকের উল্লেখ করে এবং ট্র্যাকব্যাক as ...ব্যতিক্রম হ্যান্ডলারের লক্ষ্য সহ পুরো কল স্ট্যাক সহ প্রতিটি স্থানীয় এবং গ্লোবাল নেমস্পেসের উল্লেখ করে ।
মার্টিজন পিটারস

62

যদি আপনি কোনও ফাংশনে কোনও বৈশ্বিক পরিবর্তনশীল উল্লেখ করতে চান তবে আপনি কোন ভেরিয়েবলগুলি বিশ্বব্যাপী তা ঘোষণা করতে গ্লোবাল কীওয়ার্ডটি ব্যবহার করতে পারেন । আপনাকে এটি সব ক্ষেত্রে ব্যবহার করতে হবে না (যেমন কেউ এখানে ভুলভাবে দাবি করেছেন) - যদি কোনও অভিব্যক্তিতে উল্লেখ করা নামটি স্থানীয় সুযোগে বা এই ফাংশনটি সংজ্ঞায়িত ফাংশনগুলির মধ্যে স্কোপগুলিতে পাওয়া যায় না, তবে এটি বিশ্বব্যাপী সন্ধান করা হবে ভেরিয়েবল।

তবে, যদি আপনি কোনও নতুন ভেরিয়েবলের কার্যবিবরণী হিসাবে বিশ্বব্যাপী হিসাবে ঘোষিত না হয়ে থাকেন তবে এটি স্পষ্টতই স্থানীয় হিসাবে ঘোষিত হয় এবং এটি বিদ্যমান নামের যে কোনও বৈশ্বিক ভেরিয়েবলকে ছড়িয়ে দিতে পারে।

এছাড়াও, গ্লোবাল ভেরিয়েবলগুলি দরকারী, কিছু ওওপি জিলিয়োটের বিপরীতে যারা অন্যথায় দাবি করে - বিশেষত ছোট স্ক্রিপ্টগুলির জন্য, যেখানে ওওপি ওভারকিল রয়েছে।


একেবারে রি। জেলটরা। বেশিরভাগ পাইথন ব্যবহারকারী এটি স্ক্রিপ্টিংয়ের জন্য ব্যবহার করেন এবং কোডের ছোট বিটগুলি পৃথক করার জন্য সামান্য ফাংশন তৈরি করে।
পল উজ্জাক

51

যদি আমি একটি ফাংশনে একটি বৈশ্বিক পরিবর্তনশীল তৈরি করি তবে আমি কীভাবে অন্য ফাংশনে সেই পরিবর্তনশীলটি ব্যবহার করতে পারি?

নিম্নলিখিত ফাংশন সহ আমরা একটি গ্লোবাল তৈরি করতে পারি:

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()

পরিবর্তন ছাড়াই গ্লোবাল ব্যবহার করা

আপনি কেবল এটি ব্যবহার করতে পারেন, যতক্ষণ আপনি এটি প্রত্যাখ্যান করে যে কোন বস্তুর পরিবর্তনের প্রত্যাশা করবেন না:

উদাহরণ স্বরূপ,

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

এবং এখন আমরা গ্লোবাল ভেরিয়েবল ব্যবহার করতে পারি:

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

কোনও ফাংশনের অভ্যন্তরীণ থেকে বৈশ্বিক পরিবর্তনশীলের পরিবর্তন of

গ্লোবাল ভেরিয়েবলকে অন্য কোনও অবজেক্টে চিহ্নিত করতে আপনাকে আবার গ্লোবাল কীওয়ার্ডটি ব্যবহার করতে হবে:

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!!!'

নোট করুন যে গ্লোবালের মতো একই নামের সাথে স্থানীয় ভেরিয়েবলগুলি ব্যবহার করা এড়ানো উচিত যদি না আপনি কী করছেন তা সুনির্দিষ্টভাবে না জানা এবং এটির করার খুব ভাল কারণ নেই। আমি এখনও এমন কারণের মুখোমুখি হই নি।

আমরা ক্লাসে একই আচরণ পাই

মন্তব্য অনুসরণ অনুসরণ জিজ্ঞাসা:

আমি যদি ক্লাসের ভিতরে কোনও ফাংশনের অভ্যন্তরে গ্লোবাল ভেরিয়েবল তৈরি করতে চাই এবং সেই পরিবর্তনশীলটিকে অন্য শ্রেণীর ভিতরে অন্য ফাংশনের অভ্যন্তরে ব্যবহার করতে চাই তবে কী করব?

এখানে আমি প্রদর্শন করি যে আমরা নিয়মিত ক্রিয়ায় যেমন পদ্ধতিতে করি তেমন ব্যবহার করি:

class Foo:
    def foo(self):
        global global_variable
        global_variable = 'Foo'

class Bar:
    def bar(self):
        return global_variable + '!!!'

Foo().foo()

এবং এখন:

>>> Bar().bar()
'Foo!!!'

তবে আমি আপনাকে সুপারিশ করব যে আপনি গ্লোবাল ভেরিয়েবলগুলি ব্যবহার না করে ক্লাসের বৈশিষ্ট্যগুলি ব্যবহার করুন, মডিউলটির নেমস্পেসকে বিশৃঙ্খলা এড়াতে। এছাড়াও নোট করুন যে আমরা selfএখানে আর্গুমেন্ট ব্যবহার করি না - এগুলি শ্রেণিবদ্ধ পদ্ধতি হতে পারে (সাধারণ clsতর্ক থেকে শ্রেণীর বৈশিষ্ট্যটিকে রূপান্তরিত করা যদি সহজ ) বা স্থির পদ্ধতি (না selfবা cls)।


দুর্দান্ত, তবে আমি কী করব যদি আমি একটি শ্রেণীর অভ্যন্তরে কোনও ফাংশনের ভিতরে একটি বৈশ্বিক পরিবর্তনশীল তৈরি করতে চাই এবং সেই পরিবর্তনশীলটিকে অন্য শ্রেণীর অভ্যন্তরে অন্য ফাংশনের অভ্যন্তরে ব্যবহার করতে চাই? কিন্ডা এখানে আটকে
গেলেন

2
@ অ্যানম্যানেক্স আমি জানি না আপনি আটকে কেন, কোনও নিয়মিত ক্রিয়াকলাপের মতো পদ্ধতিতেও এটি একই আচরণ। তবে আমি আপনার মন্তব্য এবং কিছু ডেমো কোড দিয়ে আমার উত্তর আপডেট করব, ঠিক আছে?
হারুন হলের

1
@ অ্যানম্যানেক্স কেমন আছেন?
হারুন হলের

আচ্ছা আমি বুঝে গেছি. সুতরাং আমি যে গ্লোবাল ভেরিয়েবল ব্যবহার করার জন্য স্পষ্টভাবে কল করতে হবে।
আনানম্যাক্স

47

ইতিমধ্যে বিদ্যমান উত্তরগুলি ছাড়াও এবং এটি আরও বিভ্রান্তিকর করার জন্য:

পাইথনে, কেবলমাত্র কোনও ফাংশনের অভ্যন্তরে উল্লেখযোগ্য ভেরিয়েবলগুলি স্পষ্টতই বিশ্বব্যাপী । যদি কোনও ভেরিয়েবলটিকে ফাংশনটির মূল অংশের মধ্যে কোনও নতুন মান নির্ধারিত করা হয় তবে এটি স্থানীয় হিসাবে ধরে নেওয়া হয় । যদি কোনও ভেরিয়েবলটিকে ফাংশনের অভ্যন্তরে কোনও নতুন মান বরাদ্দ করা হয় তবে ভেরিয়েবলটি স্পষ্টতই স্থানীয় হয় এবং আপনার এটি স্পষ্টতই 'গ্লোবাল' হিসাবে ঘোষণা করতে হবে।

প্রথমে কিছুটা অবাক হলেও, এক মুহুর্তের বিবেচনা এটি ব্যাখ্যা করে। একদিকে, নির্ধারিত ভেরিয়েবলগুলির জন্য বিশ্বব্যাপী প্রয়োজনীয়তা অনিচ্ছাকৃত পার্শ্ব প্রতিক্রিয়াগুলির বিরুদ্ধে একটি বার সরবরাহ করে। অন্যদিকে, সমস্ত বৈশ্বিক রেফারেন্সের জন্য যদি গ্লোবালটির প্রয়োজন হয় তবে আপনি সর্বদা বিশ্বব্যাপী ব্যবহার করতেন। বিল্ট-ইন ফাংশন বা আমদানি করা মডিউলের কোনও উপাদানকে প্রতিটি রেফারেন্স আপনাকে বৈশ্বিক হিসাবে ঘোষণা করতে হবে। এই বিশৃঙ্খলা পার্শ্ব প্রতিক্রিয়া সনাক্তকরণের জন্য বিশ্বব্যাপী ঘোষণার কার্যকারিতাটিকে পরাস্ত করবে।

উত্স: পাইথনে স্থানীয় এবং গ্লোবাল ভেরিয়েবলের নিয়ম কী?


34

সমান্তরাল বাস্তবায়নের সাথে, বিশ্বব্যাপী ভেরিয়েবলগুলি অপ্রত্যাশিত ফলাফলের কারণ হতে পারে যদি আপনি বুঝতে না পারেন যে কী হচ্ছে। মাল্টিপ্রসেসিংয়ের মধ্যে বৈশ্বিক পরিবর্তনশীল ব্যবহারের উদাহরণ এখানে। আমরা পরিষ্কারভাবে দেখতে পারি যে প্রতিটি প্রক্রিয়া ভেরিয়েবলের নিজস্ব অনুলিপি সহ কাজ করে:

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]

25

আপনি যা বলছেন তা হ'ল পদ্ধতিটি এইভাবে ব্যবহার করা:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

তবে আরও ভাল উপায় হ'ল বৈশ্বিক চলকটি এর মতো ব্যবহার করা:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

উভয়ই একই আউটপুট দেয়।


25

দেখা যাচ্ছে উত্তরটি সর্বদা সহজ is

mainসংজ্ঞাতে এটি দেখানোর সহজ উপায় সহ এখানে একটি ছোট নমুনা মডিউল রয়েছে :

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation

def isTheNumber():
    return helper

এটি একটি mainসংজ্ঞাতে এটি কীভাবে দেখানো হবে তা এখানে :

import TestPy

def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())

if __name__ == '__main__':
    main()

এই সাধারণ কোডটি ঠিক এর মতোই কাজ করে এবং এটি কার্যকর করে। আমি আসা করি এটা সাহায্য করবে.


1
ধন্যবাদ, আমি অজগর থেকে নতুন, তবে কিছুটা জাভা জানি। আপনি যা বলেছেন তা আমার পক্ষে কাজ করেছে। এবং ক্লাসের মধ্যে
<<<<

2
এটি আমার পক্ষে সম্ভবত সবচেয়ে কার্যকর অজগর কৌশল। আমি এই মডিউলটির নামকরণ করি global_varsএবং ডেটা শুরু করি init_global_vars, যা স্টার্টআপ স্ক্রিপ্টে ডাকা হচ্ছে। তারপরে, আমি প্রতিটি সংজ্ঞায়িত গ্লোবাল ভারের জন্য কেবল অ্যাকসেসর পদ্ধতি তৈরি করি। আমি আশা করি আমি এই একাধিকবার upvote করতে পারি! ধন্যবাদ পিটার!
swdev

1
যদি অনেকগুলি বিশ্বব্যাপী পরিবর্তনশীল থাকে এবং আমি বিশ্বব্যাপী বিবৃতি দেওয়ার পরে তাদের একের পর এক তালিকাবদ্ধ করতে চাই না তবে কী হবে?
jtlz2

23

আপনি যে ফাংশনটি ব্যবহার করতে চান তাতে আপনাকে বৈশ্বিক পরিবর্তনশীল উল্লেখ করতে হবে।

নিম্নরূপ:

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]
"""

3
'আপনি যে প্রতিটি ফাংশনটি ব্যবহার করতে চান তা' সূক্ষ্মভাবে ভুল, আপনার কাছাকাছি হওয়া উচিত: 'আপনি যে আপডেট করতে চান প্রতিটি ফাংশনে '
স্পাজম

21

আপনি আসলে স্থানীয় ভেরিয়েবলে গ্লোবাল সংরক্ষণ করছেন না, কেবল একই মূল অবজেক্টের জন্য স্থানীয় রেফারেন্স তৈরি করছেন যা আপনার আসল গ্লোবাল রেফারেন্সকে বোঝায়। মনে রাখবেন পাইথনের সমস্ত কিছুই হ'ল একটি নামকে উল্লেখ করে যা সাধারণ ক্রিয়াকলাপে কোনও কিছুই অনুলিপি করা হয় না।

কোনও সনাক্তকারী যখন পূর্বনির্ধারিত গ্লোবালকে উল্লেখ করতে হয় তখন আপনাকে যদি স্পষ্টভাবে নির্দিষ্ট করতে না হয়, তবে পরিবর্তে কোনও সনাক্তকারী নতুন স্থানীয় ভেরিয়েবল হলে আপনাকে অবশ্যই স্পষ্টভাবে নির্দিষ্ট করতে হবে (উদাহরণস্বরূপ, 'ভার' কমান্ডের মতো কিছু দিয়ে) জাভাস্ক্রিপ্টে দেখা হয়েছে)। যেহেতু যে কোনও গুরুতর এবং অ-তুচ্ছ সিস্টেমের মধ্যে স্থানীয় ভেরিয়েবলগুলি বৈশ্বিক পরিবর্তনশীলগুলির চেয়ে বেশি সাধারণ, তাই পাইথনের সিস্টেম বেশিরভাগ ক্ষেত্রেই আরও বেশি অর্থবোধ করে।

আপনার কাছে এমন একটি ভাষা থাকতে পারে যা অনুমান করার চেষ্টা করেছিল, এটি যদি বিদ্যমান থাকে তবে বৈশ্বিক ভেরিয়েবল ব্যবহার করে বা স্থানীয় ভেরিয়েবল তৈরি না করে থাকলে তা তৈরি করতে পারে। তবে, এটি খুব ত্রুটি-প্রবণ হবে। উদাহরণস্বরূপ, অন্য মডিউলটি আমদানি করা অবিচ্ছিন্নভাবে সেই নামে একটি বিশ্বব্যাপী পরিবর্তনশীল প্রবর্তন করতে পারে, আপনার প্রোগ্রামের আচরণ পরিবর্তন করে changing




14

অ্যাড অন এবং অনুসরণ হিসাবে, সমস্ত বিশ্বব্যাপী ভেরিয়েবলগুলি স্থানীয়ভাবে ঘোষণা করা এবং তারপরে একটি ফাইল ব্যবহার করুন import as:

ফাইল initval.py :

Stocksin = 300
Prices = []

ফাইল গেটটকস.পি :

import initval as iv

def getmystocks(): 
    iv.Stocksin = getstockcount()


def getmycharts():
    for ic in range(iv.Stocksin):

1
গ্লোবাল ভেরিয়েবলগুলি অন্য একটি ফাইলে সরানোর সুবিধা কী? এটি কি কেবলমাত্র একটি ক্ষুদ্র ফাইলে বৈশ্বিক ভেরিয়েবলগুলি একত্রিত করার জন্য? এবং কেন বিবৃতি ব্যবহার import ... as ...? শুধু কেন নয় import ...?
অলিব্রে

1
আহ ... আমি অবশেষে সুবিধাটি বুঝতে পেরেছি: মূল শব্দটি global:-) => +1 :-) ব্যবহার করার দরকার নেই দয়া করে আপনার উত্তরটি সম্পাদনা করুন এই জিজ্ঞাসাবাদগুলি অন্য ব্যক্তিদেরও হতে পারে তা স্পষ্ট করার জন্য। চিয়ার্স
ওলিব্রে

13

বিশ্বব্যাপী অ্যারের সুস্পষ্ট উপাদানগুলিকে লেখার জন্য স্পষ্টতই বিশ্বব্যাপী ঘোষণার প্রয়োজন হয় না, যদিও "পাইকার" এ এটি লেখার প্রয়োজন রয়েছে:

import numpy as np

hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])

def func1():
    global hostValue    # mandatory, else local.
    hostValue = 2.0

def func2():
    global hostValue    # mandatory, else UnboundLocalError.
    hostValue += 1.0

def func3():
    global hostArray    # mandatory, else local.
    hostArray = np.array([14., 15.])

def func4():            # no need for globals
    hostArray[0] = 123.4

def func5():            # no need for globals
    hostArray[1] += 1.0

def func6():            # no need for globals
    hostMatrix[1][1] = 12.

def func7():            # no need for globals
    hostMatrix[0][0] += 0.33

func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix

7

আমি এটি যুক্ত করছি কারণ আমি অন্য উত্তরের কোনওটিতে এটি দেখিনি এবং এটির মতো কিছু নিয়ে লড়াই করা কারও পক্ষে এটি কার্যকর হতে পারে। globals()ফাংশন একটি চপল বিশ্বব্যাপী প্রতীক অভিধান ফেরৎ যেখানে আপনি করতে পারেন "জাদুর" করে আপনার কোড বাকি জন্য ডেটা উপলব্ধ। উদাহরণ স্বরূপ:

from pickle import load
def loaditem(name):
    with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
        globals()[name] = load(openfile)
    return True

এবং

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

কেবল আপনাকে বৈশ্বিক নেমস্পেসের বাইরে এবং ভেরিয়েবলগুলি ডাম্প / লোড করতে দেবে। দুর্দান্ত সুবিধাজনক, কোনও গন্ধ নেই, গোলমাল নেই। খুব নিশ্চিত এটি পাইথন 3 কেবলমাত্র।


3
globals()সর্বদা স্থানীয় প্রেক্ষাপটে উপলব্ধ গ্লোবালগুলি ফেরত দেয়, তাই এখানে কোনও রূপান্তর অন্য মডিউলে প্রতিফলিত নাও হতে পারে।
কিরণ জোনালাগদদা

6

আপনি যে শ্রেণীর নামটি পরিবর্তন করতে চান তা উল্লেখ করুন।

এই উদাহরণে, রানার ফাইল কনফিগারেশন থেকে সর্বোচ্চ ব্যবহার করছে । আমি চাই যখন আমার পরীক্ষাটি রানার যখন এটি ব্যবহার করে তখন সর্বোচ্চটির মান পরিবর্তন করে change

প্রধান / config.py

max = 15000

প্রধান / runner.py

from main import config
def check_threads():
    return max < thread_count 

পরীক্ষা / runner_test.py

from main import runner                # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
   def test_threads(self):
       runner.max = 0                  # <----- 2. set global 
       check_threads()

1

গ্লোবালগুলি ভাল - একাধিক প্রসেসিং বাদে

একদিকে উইন্ডোজ / ম্যাক ওএস এবং অন্যদিকে লিনাক্স ঝামেলা হওয়ায় বিভিন্ন প্ল্যাটফর্ম / এনভায়ারমেন্টগুলিতে মাল্টিপ্রসেসিংয়ের সাথে সম্পর্কিত গ্লোবালগুলি সমস্যাজনক।

আমি আপনাকে একটি সাধারণ উদাহরণ দিয়ে এটিকে দেখাব যা কিছু সময়ের আগে আমি যে সমস্যার মধ্যে দিয়েছি out

যদি আপনি বুঝতে চান, উইন্ডোজ / ম্যাকও এবং লিনাক্সে জিনিসগুলি কেন আলাদা হয় তবে আপনার এটি জানতে হবে, একটি নতুন প্রক্রিয়া চালু করার জন্য ডিফল্ট প্রক্রিয়া ...

  • উইন্ডোজ / ম্যাকওগুলি 'স্প্যান' হয়
  • লিনাক্স হল 'কাঁটাচামচ'

এগুলি মেমোরি বরাদ্দে একটি সূচনাতে আলাদা ... (তবে আমি এটি এখানে যাই না)।

আসুন সমস্যাটি / উদাহরণটি একবার দেখুন ...

import multiprocessing

counter = 0

def do(task_id):
    global counter
    counter +=1
    print(f'task {task_id}: counter = {counter}')

if __name__ == '__main__':

    pool = multiprocessing.Pool(processes=4)
    task_ids = list(range(4))
    pool.map(do, task_ids)

উইন্ডোজ

আপনি যদি এটি উইন্ডোয় চালান (এবং আমি ম্যাকওএস-তেও অনুমান করি), আপনি নিম্নলিখিত আউটপুটটি পান ...

task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4

লিনাক্স

আপনি যদি এটি লিনাক্সে চালনা করেন তবে পরিবর্তে নিম্নলিখিতটি পান।

task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.