পাইথন ফাংশন গ্লোবাল ভেরিয়েবল?


271

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

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x = func_A()
   # Do things
   return x

func_A()
func_B()

কি xদ্বিতীয় ফাংশন ব্যবহার সম্পর্কে বিশ্বব্যাপী কপি একই মান আছে xযে func_aব্যবহারসমূহ এবং মডিফাই? সংজ্ঞার পরে ফাংশনগুলি কল করার সময়, অর্ডারটি কী ব্যাপার?


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

উত্তর:


412

আপনি যদি কেবল কোনও গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে চান তবে কেবল তার নামটি ব্যবহার করুন। তবে এর মান পরিবর্তন করতে আপনার globalকীওয়ার্ডটি ব্যবহার করতে হবে ।

যেমন

global someVar
someVar = 55

এটি গ্লোবাল ভেরিয়েবলের মান 55 এ পরিবর্তন করবে Otherwise অন্যথায় এটি কেবলমাত্র স্থানীয় ভেরিয়েবলের জন্য 55 নির্ধারণ করে।

ফাংশন সংজ্ঞা তালিকার ক্রম কোনও ব্যাপার নয় (ধরে নিই তারা কোনওভাবে একে অপরকে উল্লেখ করে না), তাদের যে ক্রম বলা হয় তা তা করে।


2
আমি যে কোডটি দিয়েছি তা হল, ফানক_বি এক্সের গ্লোবাল অনুলিপি (ফানক_এ থেকে প্রাপ্ত হিসাবে) এর কাজগুলি (1) করছে, (2) ফানক_এ এর ফলাফলের একই মান সহ একটি স্থানীয় ভেরিয়েবল এক্সে বা (3) থেকে একটি স্থানীয় ভেরিয়েবল এক্স যার কোনও মূল্য নেই এবং (সংকলকের চোখে) "কিছু মান" বা x এর সাথে কোন সম্পর্ক নেই?
অক্ষত শেখর

xইন func_Bএকটি স্থানীয় ভেরিয়েবল যা কলটির রিটার্ন মান থেকে এর মান পায় func_A- তাই আমি অনুমান করি যে এটি আপনার (2) করে দেবে
লেভন

ঠিক আছে, ধরা যাক এক্স ফানক_এ দ্বারা উত্পাদিত কোনও ধরণের একটি এলোমেলো ক্রম ছিল (অর্থাত্ ফান_এ প্রতিটি সময় পরিচালিত হওয়ার সময় একটি আলাদা এক্স তৈরি করেছিল)) ফানক_এটি যখন তৈরি হয়েছিল তখন মূলত যা তৈরি হয়েছিল তার চেয়ে আলাদা x সংশোধন করবে বলা হয়? যদি তা হয় তবে আমি কীভাবে এটি সংশোধন করতে পারি?
অক্ষত শেখর

1
হ্যাঁ, যদি func_Aপ্রতিটি রান চলাকালীন গ্লোবাল ভেরিয়েবল পরিবর্তন হয় এবং এটি func_Bব্যবহার করতে ফিরে আসে , তবে func_Bপ্রতিবার পরিবর্তিত মান নিয়ে কাজ করবে। আপনার "কীভাবে এটি ঠিক করবেন" সম্পর্কে আমি নিশ্চিত নই। আপনি আপনার বর্তমান / মূল প্রশ্নের সর্বাধিক সহায়ক উত্তরটি গ্রহণ করতে চাইতে পারেন এবং তারপরে অনুসরণীয় প্রশ্নের মতো দেখতে কী আলাদা তা সম্পর্কে একটি আলাদা প্রশ্ন খোলার বিষয়টি বিবেচনা করতে পারেন।
লেভন

1
আসলে এটি এক্স কী তা নির্ভর করে। X যদি অপরিবর্তনীয় থাকে, তবে ফানক_বিতে এক্সটি এতে থাকবে, কারণ এটি স্থানীয়ভাবে ঘোষিত হয় যদিও তাদের মান একই থাকে। এটি টিপলস, ইনটসের ক্ষেত্রে প্রযোজ্য ... এটি যদি কোনও তালিকার উদাহরণ হিসাবে থাকে এবং আপনি x.append("...")এটি করেন তবে এটি বিশ্বব্যাপী পরিবর্তনশীল x যা পরিবর্তিত হয়, কারণ স্থানীয় একটি বিশ্বব্যাপী উল্লেখ করে।
jadkik94

110

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

আসুন কী ঘটে তা দেখতে আপনার সিউডোকোডের একটি পরিবর্তিত সংস্করণ দেখুন:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

প্রকৃতপক্ষে, আপনি func_Bনামটির সাথে চলকটি আবার লিখতে পারেন x_localএবং এটি অভিন্নভাবে কাজ করবে।

আপনার ক্রিয়াকলাপগুলি যে ক্রিয়াকলাপটি গ্লোবাল এক্স এর মান পরিবর্তন করে তা ক্রম হিসাবে কেবল অর্ডারটি গুরুত্বপূর্ণ। আমাদের উদাহরণস্বরূপ, func_Bকলগুলি যেহেতু অর্ডার কোনও বিষয় নয় func_A। এই উদাহরণে, আদেশ অর্থে গুরুত্বপূর্ণ:

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

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

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

কল না করা সত্ত্বেও গ্লোবাল এক্স অ্যাক্সেস করা create_locallyএবং access_only- এর মধ্যে পার্থক্যটি লক্ষ্য করুন এবং এটি কোনও ব্যবহার না করেও এটি একটি স্থানীয় কপি তৈরি করে যেহেতু এটি একটি মূল্য নির্ধারণ করেaccess_onlyglobalcreate_locallyglobal

এখানে বিভ্রান্তি হ'ল কেন আপনার বৈশ্বিক ভেরিয়েবলগুলি ব্যবহার করা উচিত নয়।


2
আমি মনে করি না এটি অনুশীলনটি খুব বিভ্রান্তিকর, আপনাকে কেবল অজগরটির স্কোপিংয়ের নিয়মগুলি বুঝতে হবে ।
কেসি কুবাল 18

20

অন্যরা যেমন উল্লেখ করেছে, আপনি globalযখন কোনও ফাংশনটি বৈশ্বিক চলক পরিবর্তন করতে সক্ষম হবেন তখন আপনাকে কোনও ফাংশনে ভেরিয়েবল ঘোষণা করতে হবে। আপনি যদি কেবল এটি অ্যাক্সেস করতে চান তবে আপনার প্রয়োজন হবে নাglobal

তার আরও কিছুটা বিশদে যাওয়ার জন্য, "সংশোধন" এর অর্থ হ'ল: যদি আপনি বিশ্বব্যাপী নামটি আবার যুক্ত করতে চান তবে এটি কোনও ভিন্ন অবজেক্টের দিকে নির্দেশ করে, নামটি অবশ্যই ঘোষণা করতে হবেglobal

অনেকগুলি ক্রিয়াকলাপ যা কোনও বস্তুকে সংশোধন করে (পরিবর্তিত করে) গ্লোবাল নামটিকে কোনও ভিন্ন অবজেক্টের দিকে নির্দেশ করতে পুনরায় বাঁধাই করে না এবং তাই ফাংশনে নাম ঘোষণা না করে সেগুলি সবই বৈধglobal

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object

8

এখানে প্যারামিটারের একটি ডিফল্ট মান হিসাবে বিশ্বব্যাপী ব্যবহার করে এমন একটি মামলা আমাকে ধরা দিয়েছে।

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

আমি পরমের প্রত্যাশা করেছি 42 এর একটি মান হবে। পাইথন ২.7 গ্লোবভারের মূল্যায়ন করে যখন এটি প্রথম ফাংশন ফানকে পার্স করেছে। গ্লোবভারের মান পরিবর্তন করা পরমের কাছে নির্ধারিত ডিফল্ট মানকে প্রভাবিত করে না। নিম্নলিখিত হিসাবে মূল্যায়ন বিলম্ব করা, আমার যেমন প্রয়োজন তেমন কাজ করেছে।

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

অথবা, আপনি যদি নিরাপদে থাকতে চান,

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values

এটি আমাকে ডিফল্ট মান হিসাবে একটি খালি তালিকা নির্ধারণের সমস্যার কথা মনে করিয়ে দেয় । এবং, উদাহরণস্বরূপ, সাধারণ তুলনার পরিবর্তে isকিছু আছে কিনা তা পরীক্ষা Noneকরে দেখুন ==
berna1111

6

আপনি কোনও ফাংশনের অভ্যন্তরে সরাসরি গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে পারেন। আপনি যদি সেই গ্লোবাল ভেরিয়েবলের মান পরিবর্তন করতে চান তবে "গ্লোবাল ভেরিয়েবল_নাম" ব্যবহার করুন। নিম্নলিখিত উদাহরণটি দেখুন:

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

সাধারণভাবে বলতে গেলে, এটি কোনও ভাল প্রোগ্রামিং অনুশীলন নয়। নেমস্পেস যুক্তি ভঙ্গ করে, কোড বুঝতে এবং ডিবাগ করা কঠিন হয়ে উঠতে পারে।


2

আপনি globalযখন বৈশ্বিক ভেরিয়েবলের জন্য নির্ধারিত মান পরিবর্তন করতে চান তখন আপনাকে অবশ্যই ঘোষণাটি ব্যবহার করতে হবে ।

গ্লোবাল ভেরিয়েবল থেকে আপনার পড়ার দরকার নেই। নোট করুন যে কোনও বস্তুর উপর কোনও পদ্ধতিতে কল করা (এমনকি এটি যদি সেই বস্তুর মধ্যে থাকা ডেটার পরিবর্তিত করে) তখনও সেই বস্তুর (অনুপস্থিত প্রতিফলিত যাদু) ধারণের পরিবর্তনের মান পরিবর্তন হয় না।


2
এই শব্দবন্ধ দুর্ভাগ্যজনক। পাইথনে, একটি ভেরিয়েবলের জন্য নির্ধারিত মান একটি রেফারেন্স, সুতরাং এটি প্রযুক্তিগতভাবে সঠিক (এবং আপনার কোনও সন্দেহ নেই যে আপনি এটি বোঝাতে চেয়েছিলেন), তবে অনেক পাঠক "মানকে পরিবর্তিত করুন" "অবজেক্টটিকে রূপান্তরিত" হিসাবে ব্যাখ্যা করতে পারেন, যা এটি নয় কেস - xs.append(xs.pop(0))ছাড়া ঠিক ঠিক কাজ করে global xs

@ ডেলান আমার উত্তরটি সাবধানতার সাথে উচ্চারিত হয়েছে তবে আমি স্পষ্ট করে বলব।
মার্সিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.