मैं चर की चर संख्या कैसे बनाऊं?


363

मैं पायथन में चर चर कैसे पूरा करूं?

यहाँ एक विस्तृत मैनुअल प्रविष्टि है, उदाहरण के लिए: चर चर

मैंने सुना है कि यह सामान्य रूप से एक बुरा विचार है, और यह पायथन में एक सुरक्षा छेद है। क्या यह सच है?


39
यह रखरखाव और डिबगिंग पहलुओं का कारण बनता है जो आतंक का कारण बनता है। यह पता लगाने की कोशिश करें कि आपके कोड में कोई स्थान नहीं होने पर परिवर्तनशील 'foo' कहाँ बदल गया है जहाँ आप वास्तव में 'foo' बदलते हैं। आगे कल्पना कीजिए कि यह किसी और का कोड है जिसे आपको बनाए रखना है ... ठीक है, अब आप अपने खुशहाल स्थान पर जा सकते हैं।
ग्लेन जैकमैन

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

यहां सभी प्रतिक्रियाएं मानती हैं कि आपके पास आधार चर तक पहुंच है जिसे आप नाम से गतिशील रूप से एक्सेस करना चाहते हैं, जो हमेशा ऐसा नहीं होता है। मुझे लगता है कि PHP में उदाहरण के व्यवहार को पुन: पेश करने के लिए सबसे सामान्य दृष्टिकोण eval () का उपयोग करना है: var_name = 'foo'; बार = 5; output = eval (var_name)
लुइस

1
आप उनके लिए अंतर्निहित शब्दकोशों तक पहुंचकर अपने वैश्विक और स्थानीय चर को संशोधित कर सकते हैं; यह एक रखरखाव के दृष्टिकोण से एक भयानक विचार है ... लेकिन यह ग्लोबल्स () अपडेट () और स्थानीय लोगों () अपडेट () या (उन दोनों में से किसी भी संदर्भ को संदर्भित करने से बचा सकता है ) और किसी अन्य शब्दकोश की तरह उपयोग करके किया जा सकता है। )। नहीं लिखा ... लेकिन आपको पता होना चाहिए कि यह संभव है।
जिम डेनिस

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

जवाबों:


296

इसे पूरा करने के लिए आप शब्दकोशों का उपयोग कर सकते हैं । शब्दकोश कुंजियों और मूल्यों के भंडार हैं।

>>> 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 और अन्य परिचालनों में पुनरावृत्ति का समर्थन करती हैं , जिन्हें एक प्रमुख के साथ अजीब कुंजी प्रबंधन की आवश्यकता होती है।


88

getattrनाम से किसी ऑब्जेक्ट पर विशेषता प्राप्त करने के लिए अंतर्निहित फ़ंक्शन का उपयोग करें । आवश्यकतानुसार नाम बदलें।

obj.spam = 'eggs'
name = 'spam'
getattr(obj, name)  # returns 'eggs'

70

यह एक अच्छा विचार नहीं है। यदि आप एक वैश्विक वैरिएबल का उपयोग कर रहे हैं तो आप उपयोग कर सकते हैं globals()

>>> a = 10
>>> globals()['a']
10

यदि आप किसी स्थानीय स्कोप में वैरिएबल का उपयोग करना चाहते हैं, जिसका आप उपयोग कर सकते हैं locals(), लेकिन आप लौटे हुए मान को मान असाइन नहीं कर सकते।

एक बेहतर उपाय यह है कि getattrअपने चर का उपयोग किसी शब्दकोश में किया जाए या फिर उन्हें नाम से एक्सेस किया जाए।


स्थानीय लोग ()। अद्यतन ({'new_local_var': 'कुछ स्थानीय मूल्य')) मेरे लिए पायथन 3.7.6 में ठीक काम करता है; इसलिए मुझे यकीन नहीं है कि आपके कहने का मतलब क्या है जब आप इसके माध्यम से मूल्यों को निर्दिष्ट नहीं कर सकते।
जिम डेनिस

दिए गए x = "foo"और locals()["x"] = "bar"उपयोग करने से जेथॉन 2.5.2 के लिए print xआउटपुट मिलता है bar। यह मैक्सिमो में एक ऑन डिमांड ऑटोमेशन स्क्रिप्ट के साथ परीक्षण किया गया था ।
प्रीचर

37

जब भी आप परिवर्तनशील चर का उपयोग करना चाहते हैं, तो शब्दकोश का उपयोग करना बेहतर होगा। इसलिए लिखने के बजाय

$foo = "bar"
$$foo = "baz"

तुम लिखो

mydict = {}
foo = "bar"
mydict[foo] = "baz"

इस तरह आप गलती से पहले से मौजूद चर (जो सुरक्षा पहलू है) को अधिलेखित नहीं करेंगे और आपके पास "नामस्थान" अलग हो सकते हैं।


34

नए कोडर कभी-कभी इस तरह कोड लिखते हैं:

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जुड़े मूल्यों के साथ नाम के एक बैग के लिए।


12

एक शब्दकोश के बजाय आप 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)

10

यदि आप किसी वस्तु का उपयोग नहीं करना चाहते हैं, तब भी आप 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()इसे कर सकते हैं
गिलियूम लेब्रेटन

9

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

6

मैं इस प्रश्न का उत्तर दे रहा हूं: एक चर का नाम स्ट्रिंग में दिए गए मूल्य को कैसे प्राप्त करें? जो इस प्रश्न के लिंक के साथ एक डुप्लिकेट के रूप में बंद है।

प्रश्न में चर एक वस्तु (उदाहरण के लिए एक वर्ग का हिस्सा) का हिस्सा हैं तो कुछ उपयोगी कार्यों वास्तव में प्राप्त करने के लिए कर रहे हैं 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

"वास्तव में प्रारंभिक नहीं है"


5

उपयोग globals()

आप वास्तव में वैश्विक स्तर पर वैरिएबल को गतिशील रूप से असाइन कर सकते हैं, उदाहरण के लिए, यदि आप 10 वैरिएबल चाहते हैं जिसे वैश्विक दायरे में एक्सेस किया जा सकता है i_1, तो i_2... i_10:

for i in range(10):
    globals()['i_{}'.format(i)] = 'a'

यह इन 10 चर में से सभी को 'ए' प्रदान करेगा, निश्चित रूप से आप मूल्य को गतिशील रूप से भी बदल सकते हैं। इन सभी चर को अब विश्व स्तर पर घोषित अन्य चर की तरह एक्सेस किया जा सकता है:

>>> i_5
'a'

4

आपको उस व्यवहार को प्राप्त करने के लिए 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

3

आम सहमति इसके लिए एक शब्दकोश का उपयोग करना है - अन्य उत्तरों को देखें। यह ज्यादातर मामलों के लिए एक अच्छा विचार है, हालांकि, इससे कई पहलू उत्पन्न होते हैं:

  • आप स्वयं इस शब्दकोश के लिए ज़िम्मेदार होंगे, जिसमें कचरा संग्रह (इन-तानाशाह चर) आदि शामिल हैं।
  • चर चर के लिए कोई स्थानीयता या वैश्विकता नहीं है, यह शब्दकोश की वैश्विकता पर निर्भर करता है
  • यदि आप एक चर नाम बदलना चाहते हैं, तो आपको इसे मैन्युअल रूप से करना होगा
  • हालाँकि, आप बहुत अधिक लचीले हैं, उदाहरण के लिए
    • आप मौजूदा चर को अधिलेखित करने का निर्णय ले सकते हैं या ...
    • ... कांस्टेबल चर लागू करने के लिए चुनें
    • विभिन्न प्रकारों के लिए ओवरराइटिंग पर एक अपवाद बढ़ाने के लिए
    • आदि।

उस ने कहा, मैंने एक वैरिएबल चर प्रबंधक -क्लास लागू किया है जो उपरोक्त विचारों में से कुछ प्रदान करता है। यह अजगर 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

मैंने अजगर 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'


संदर्भ:
https://www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936


0

चरों का कोई भी सेट क्लास में भी लपेटा जा सकता है। "वैरिएबल" चर को रनटाइम के दौरान वर्ग उदाहरण में सीधे __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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.