मैं पायथन में चर चर कैसे पूरा करूं?
यहाँ एक विस्तृत मैनुअल प्रविष्टि है, उदाहरण के लिए: चर चर
मैंने सुना है कि यह सामान्य रूप से एक बुरा विचार है, और यह पायथन में एक सुरक्षा छेद है। क्या यह सच है?
मैं पायथन में चर चर कैसे पूरा करूं?
यहाँ एक विस्तृत मैनुअल प्रविष्टि है, उदाहरण के लिए: चर चर
मैंने सुना है कि यह सामान्य रूप से एक बुरा विचार है, और यह पायथन में एक सुरक्षा छेद है। क्या यह सच है?
जवाबों:
इसे पूरा करने के लिए आप शब्दकोशों का उपयोग कर सकते हैं । शब्दकोश कुंजियों और मूल्यों के भंडार हैं।
>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2
आप सुरक्षा जोखिम के बिना चर चर के प्रभाव को प्राप्त करने के लिए चर कुंजी नामों का उपयोग कर सकते हैं।
>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'
ऐसे मामलों के लिए जहां आप कुछ करने की सोच रहे हैं
var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...
एक सूची एक तानाशाह की तुलना में अधिक उपयुक्त हो सकती है। पूर्णांक सूचकांकों के साथ एक सूची वस्तुओं के क्रमबद्ध क्रम का प्रतिनिधित्व करती है:
lst = ['foo', 'bar', 'baz']
print(lst[1]) # prints bar, because indices start at 0
lst.append('potatoes') # lst is now ['foo', 'bar', 'baz', 'potatoes']
क्रमबद्ध अनुक्रमों के लिए, पूर्णांक कुंजियों के साथ सूचियों की तुलना में सूचियाँ अधिक सुविधाजनक होती हैं, क्योंकि सूचियाँ सूचकांक क्रम, स्लाइसिंगappend
और अन्य परिचालनों में पुनरावृत्ति का समर्थन करती हैं , जिन्हें एक प्रमुख के साथ अजीब कुंजी प्रबंधन की आवश्यकता होती है।
getattr
नाम से किसी ऑब्जेक्ट पर विशेषता प्राप्त करने के लिए अंतर्निहित फ़ंक्शन का उपयोग करें । आवश्यकतानुसार नाम बदलें।
obj.spam = 'eggs'
name = 'spam'
getattr(obj, name) # returns 'eggs'
यह एक अच्छा विचार नहीं है। यदि आप एक वैश्विक वैरिएबल का उपयोग कर रहे हैं तो आप उपयोग कर सकते हैं globals()
।
>>> a = 10
>>> globals()['a']
10
यदि आप किसी स्थानीय स्कोप में वैरिएबल का उपयोग करना चाहते हैं, जिसका आप उपयोग कर सकते हैं locals()
, लेकिन आप लौटे हुए मान को मान असाइन नहीं कर सकते।
एक बेहतर उपाय यह है कि getattr
अपने चर का उपयोग किसी शब्दकोश में किया जाए या फिर उन्हें नाम से एक्सेस किया जाए।
जब भी आप परिवर्तनशील चर का उपयोग करना चाहते हैं, तो शब्दकोश का उपयोग करना बेहतर होगा। इसलिए लिखने के बजाय
$foo = "bar"
$$foo = "baz"
तुम लिखो
mydict = {}
foo = "bar"
mydict[foo] = "baz"
इस तरह आप गलती से पहले से मौजूद चर (जो सुरक्षा पहलू है) को अधिलेखित नहीं करेंगे और आपके पास "नामस्थान" अलग हो सकते हैं।
नए कोडर कभी-कभी इस तरह कोड लिखते हैं:
my_calculator.button_0 = tkinter.Button(root, text=0)
my_calculator.button_1 = tkinter.Button(root, text=1)
my_calculator.button_2 = tkinter.Button(root, text=2)
...
कोडर को तब O ( m * n ) के कोडिंग प्रयास के साथ नामित चर के ढेर के साथ छोड़ दिया जाता है , जहाँ m नामांकित चर की संख्या होती है और n वह संख्या होती है जब चर के समूह को एक्सेस करने की आवश्यकता होती है (निर्माण सहित) )। अधिक सूक्ष्म शुरुआत करने वाला देखता है कि उनमें से प्रत्येक पंक्ति में एकमात्र अंतर एक संख्या है जो एक नियम के आधार पर बदलता है, और एक लूप का उपयोग करने का निर्णय लेता है। हालांकि, वे उन चर नामों को गतिशील रूप से बनाने के तरीके पर अटक जाते हैं, और कुछ इस तरह की कोशिश कर सकते हैं:
for i in range(10):
my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)
उन्हें जल्द ही पता चलता है कि यह काम नहीं करता है।
यदि कार्यक्रम को मनमाने ढंग से चर "नामों की आवश्यकता होती है," एक शब्दकोश सबसे अच्छा विकल्प है, जैसा कि अन्य उत्तरों में समझाया गया है। हालाँकि, यदि आप बस कई चर बनाने की कोशिश कर रहे हैं और आप पूर्णांकों के अनुक्रम के साथ उनका जिक्र करने से गुरेज नहीं करते हैं, तो आप शायद इसकी तलाश कर रहे हैं list
। यह विशेष रूप से सच है यदि आपका डेटा सजातीय है, जैसे कि दैनिक तापमान रीडिंग, साप्ताहिक क्विज़ स्कोर, या ग्राफ़िकल विजेट का ग्रिड।
इसे निम्नानुसार इकट्ठा किया जा सकता है:
my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))
यह list
भी एक पंक्ति में एक समझ के साथ बनाया जा सकता है:
my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
या तो मामले में परिणाम एक आबादी है list
, पहले तत्व के साथ पहुँचा my_calculator.buttons[0]
, अगले के साथ my_calculator.buttons[1]
, और इसी तरह। "आधार" चर नाम का नाम बन जाता है list
और इसे एक्सेस करने के लिए अलग-अलग पहचानकर्ता का उपयोग किया जाता है।
अंत में, अन्य डेटा संरचनाओं को मत भूलना, जैसे कि set
- यह एक शब्दकोश के समान है, सिवाय इसके कि प्रत्येक "नाम" में इसके साथ एक मूल्य नहीं है। यदि आपको बस वस्तुओं के "बैग" की आवश्यकता है, तो यह एक बढ़िया विकल्प हो सकता है। कुछ इस तरह के बजाय:
keyword_1 = 'apple'
keyword_2 = 'banana'
if query == keyword_1 or query == keyword_2:
print('Match.')
आपके पास यह होगा:
keywords = {'apple', 'banana'}
if query in keywords:
print('Match.')
एक का प्रयोग करें list
समान वस्तुओं की एक अनुक्रम, एक के लिए set
वस्तुओं का एक मनमाने ढंग से आदेश दिया बैग, या एक के लिए dict
जुड़े मूल्यों के साथ नाम के एक बैग के लिए।
एक शब्दकोश के बजाय आप namedtuple
संग्रह मॉड्यूल से भी उपयोग कर सकते हैं , जिससे पहुंच आसान हो जाती है।
उदाहरण के लिए:
# using dictionary
variables = {}
variables["first"] = 34
variables["second"] = 45
print(variables["first"], variables["second"])
# using namedtuple
Variables = namedtuple('Variables', ['first', 'second'])
vars = Variables(34, 45)
print(vars.first, vars.second)
यदि आप किसी वस्तु का उपयोग नहीं करना चाहते हैं, तब भी आप setattr()
अपने वर्तमान मॉड्यूल के अंदर उपयोग कर सकते हैं :
import sys
current_module = module = sys.modules[__name__] # i.e the "file" where your code is written
setattr(current_module, 'variable_name', 15) # 15 is the value you assign to the var
print(variable_name) # >>> 15, created from a string
__dict__
हालांकि यह वेरिएबल के साथ काम नहीं करता है । मुझे आश्चर्य है कि अगर गतिशील रूप से किसी भी वैश्विक चर को बनाने के लिए एक सामान्य तंत्र है ।
globals()
इसे कर सकते हैं
SimpleNamespace
वर्ग के साथ नई विशेषताओं बनाने के लिए इस्तेमाल किया जा सकता है setattr
, या उपवर्ग SimpleNamespace
और नई विशेषता नाम (चर) जोड़ने के लिए अपने स्वयं के समारोह पैदा करते हैं।
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a
मैं इस प्रश्न का उत्तर दे रहा हूं: एक चर का नाम स्ट्रिंग में दिए गए मूल्य को कैसे प्राप्त करें? जो इस प्रश्न के लिंक के साथ एक डुप्लिकेट के रूप में बंद है।
प्रश्न में चर एक वस्तु (उदाहरण के लिए एक वर्ग का हिस्सा) का हिस्सा हैं तो कुछ उपयोगी कार्यों वास्तव में प्राप्त करने के लिए कर रहे हैं hasattr
, getattr
और setattr
।
तो उदाहरण के लिए आपके पास हो सकता है:
class Variables(object):
def __init__(self):
self.foo = "initial_variable"
def create_new_var(self,name,value):
setattr(self,name,value)
def get_var(self,name):
if hasattr(self,name):
return getattr(self,name)
else:
raise("Class does not have a variable named: "+name)
तो आप कर सकते हैं:
v = Variables()
v.get_var("foo")
"Initial_variable"
v.create_new_var(v.foo,"is actually not initial")
v.initial_variable
"वास्तव में प्रारंभिक नहीं है"
उपयोग globals()
आप वास्तव में वैश्विक स्तर पर वैरिएबल को गतिशील रूप से असाइन कर सकते हैं, उदाहरण के लिए, यदि आप 10 वैरिएबल चाहते हैं जिसे वैश्विक दायरे में एक्सेस किया जा सकता है i_1
, तो i_2
... i_10
:
for i in range(10):
globals()['i_{}'.format(i)] = 'a'
यह इन 10 चर में से सभी को 'ए' प्रदान करेगा, निश्चित रूप से आप मूल्य को गतिशील रूप से भी बदल सकते हैं। इन सभी चर को अब विश्व स्तर पर घोषित अन्य चर की तरह एक्सेस किया जा सकता है:
>>> i_5
'a'
आपको उस व्यवहार को प्राप्त करने के लिए globals()
निर्मित विधि का उपयोग करना होगा:
def var_of_var(k, v):
globals()[k] = v
print variable_name # NameError: name 'variable_name' is not defined
some_name = 'variable_name'
globals()[some_name] = 123
print variable_name # 123
some_name = 'variable_name2'
var_of_var(some_name, 456)
print variable_name2 # 456
आम सहमति इसके लिए एक शब्दकोश का उपयोग करना है - अन्य उत्तरों को देखें। यह ज्यादातर मामलों के लिए एक अच्छा विचार है, हालांकि, इससे कई पहलू उत्पन्न होते हैं:
उस ने कहा, मैंने एक वैरिएबल चर प्रबंधक -क्लास लागू किया है जो उपरोक्त विचारों में से कुछ प्रदान करता है। यह अजगर 2 और 3 के लिए काम करता है।
आप इस तरह वर्ग का उपयोग करेंगे :
from variableVariablesManager import VariableVariablesManager
myVars = VariableVariablesManager()
myVars['test'] = 25
print(myVars['test'])
# define a const variable
myVars.defineConstVariable('myconst', 13)
try:
myVars['myconst'] = 14 # <- this raises an error, since 'myconst' must not be changed
print("not allowed")
except AttributeError as e:
pass
# rename a variable
myVars.renameVariable('myconst', 'myconstOther')
# preserve locality
def testLocalVar():
myVars = VariableVariablesManager()
myVars['test'] = 13
print("inside function myVars['test']:", myVars['test'])
testLocalVar()
print("outside function myVars['test']:", myVars['test'])
# define a global variable
myVars.defineGlobalVariable('globalVar', 12)
def testGlobalVar():
myVars = VariableVariablesManager()
print("inside function myVars['globalVar']:", myVars['globalVar'])
myVars['globalVar'] = 13
print("inside function myVars['globalVar'] (having been changed):", myVars['globalVar'])
testGlobalVar()
print("outside function myVars['globalVar']:", myVars['globalVar'])
यदि आप केवल एक ही प्रकार के साथ चर की ओवरराइटिंग की अनुमति देना चाहते हैं:
myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)
मैंने अजगर 3.7.3 में दोनों की कोशिश की है, आप ग्लोबल्स () या vars () का उपयोग कर सकते हैं
>>> food #Error
>>> milkshake #Error
>>> food="bread"
>>> drink="milkshake"
>>> globals()[food] = "strawberry flavor"
>>> vars()[drink] = "chocolate flavor"
>>> bread
'strawberry flavor'
>>> milkshake
'chocolate flavor'
>>> globals()[drink]
'chocolate flavor'
>>> vars()[food]
'strawberry flavor'
चरों का कोई भी सेट क्लास में भी लपेटा जा सकता है। "वैरिएबल" चर को रनटाइम के दौरान वर्ग उदाहरण में सीधे __dict__ विशेषता के माध्यम से अंतर्निहित शब्दकोश में प्रवेश करके जोड़ा जा सकता है।
निम्न कोड वेरिएबल्स वर्ग को परिभाषित करता है, जो निर्माण के दौरान इसके उदाहरण में चर (इस मामले में विशेषताएँ) जोड़ता है। परिवर्तनीय नाम एक निर्दिष्ट सूची से लिए गए हैं (जो, उदाहरण के लिए, प्रोग्राम कोड द्वारा उत्पन्न किया जा सकता है):
# some list of variable names
L = ['a', 'b', 'c']
class Variables:
def __init__(self, L):
for item in L:
self.__dict__[item] = 100
v = Variables(L)
print(v.a, v.b, v.c)
#will produce 100 100 100