আমি কীভাবে একটি চলক সংখ্যা ভেরিয়েবল তৈরি করব?


363

পাইথনে আমি কীভাবে পরিবর্তনশীল ভেরিয়েবলগুলি সম্পাদন করতে পারি?

উদাহরণস্বরূপ: এখানে একটি বিশদ ম্যানুয়াল এন্ট্রি রয়েছে V

আমি শুনেছি এটি সাধারণভাবে খারাপ ধারণা এবং এটি পাইথনের একটি সুরক্ষা গর্ত hole এটা কি সত্যি?


39
এটি হ'ল রক্ষণাবেক্ষণ এবং ডিবাগিং দিকগুলি যা হরর সৃষ্টি করে cause আপনার কোডে কোনও স্থান নেই যেখানে আপনি 'foo' পরিবর্তন করেছেন সেখানে ভেরিয়েবল 'foo' কোথায় পরিবর্তিত হয়েছে তা অনুসন্ধান করার চেষ্টা করার কথা ভাবুন। আরও কল্পনা করুন যে এটি অন্য কারও কোড যা আপনার বজায় রাখতে হবে ... ঠিক আছে, আপনি এখন আপনার সুখী জায়গায় যেতে পারেন।
গ্লেন জ্যাকম্যান

4
আরও একটি সমস্যা যা এখনও অবধি উল্লেখ করা হয়নি তা হল যদি এই জাতীয় গতিশীলভাবে তৈরি ভেরিয়েবলটির যুক্তি আপনার যুক্তিতে ব্যবহৃত একটি চলক হিসাবে একই থাকে name আপনি প্রদত্ত ইনপুটটিতে জিম্মি হিসাবে আপনার সফ্টওয়্যারটি মূলত খুলুন।
হোল্ডেনওয়েব

এখানে সমস্ত প্রতিক্রিয়া ধরে নিয়েছে যে নাম অনুসারে আপনি গতিশীলভাবে অ্যাক্সেস করতে চান এমন বেস ভেরিয়েবলগুলিতে আপনার অ্যাক্সেস রয়েছে যা সর্বদা ক্ষেত্রে হয় না। আমি মনে করি পিএইচপি-তে উদাহরণ ব্যবহারের পুনরুত্পাদন করার সর্বাধিক সাধারণ পন্থা হল এভ্যাল () এর মতো ব্যবহার করা: var_name = 'foo'; বার = 5; আউটপুট = ইভাল (বর্ণ_নাম)
লুইস

1
আপনি তাদের জন্য অন্তর্নিহিত অভিধানগুলি অ্যাক্সেস করে আপনার বিশ্বব্যাপী এবং স্থানীয় পরিবর্তনগুলি পরিবর্তন করতে পারেন; এটি রক্ষণাবেক্ষণের দৃষ্টিভঙ্গি থেকে একটি ভয়ঙ্কর ধারণা ... তবে এটি গ্লোবাল ()। আপডেট () এবং স্থানীয়দের () আপডেট () এর মাধ্যমে করা যেতে পারে (বা এর যে কোনও একটি থেকে ডিক রেফারেন্স সংরক্ষণ করে এবং এটি অন্য কোনও অভিধানের মতো ব্যবহার করে )। প্রস্তাবিত নয় ... তবে আপনার জানা উচিত এটি সম্ভব possible
জিম ডেনিস

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

উত্তর:


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

আদেশ সিকোয়েন্স জন্য, তালিকা কারণ তালিকা সূচক আদেশ, মধ্যে পুনরাবৃত্তির সমর্থন পূর্ণসংখ্যা কী এর মাধ্যমে dicts চেয়ে আরও বেশি সুবিধাজনক হয় slicing , append, এবং অন্যান্য অপারেশন করে একটি অভি সঙ্গে বিশ্রী কী ব্যবস্থাপনা প্রয়োজন।


88

getattrনামের সাথে কোনও অবজেক্টের একটি বৈশিষ্ট্য পেতে অন্তর্নির্মিত ফাংশনটি ব্যবহার করুন । প্রয়োজন মতো নামটি সংশোধন করুন।

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

70

এটি একটি ভাল ধারণা না. আপনি যদি কোনও বিশ্বব্যাপী ভেরিয়েবল অ্যাক্সেস করে থাকেন তবে আপনি এটি ব্যবহার করতে পারেন globals()

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

আপনি যদি স্থানীয় স্কোপে কোনও পরিবর্তনশীল অ্যাক্সেস করতে চান locals()তবে আপনি ব্যবহার করতে পারেন তবে আপনি ফেরত ডিকের মান নির্ধারণ করতে পারবেন না।

getattrএকটি অভিধানে আপনার ভেরিয়েবলগুলি ব্যবহার বা সঞ্চয় করে তারপরে নাম দ্বারা অ্যাক্সেস করা এর থেকে ভাল সমাধান solution


স্থানীয়রা ()। আপডেট (new 'new_local_var': 'কিছু লোকাল ভ্যালু' on) পাইথন ৩.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)
...

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

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

এটি 'এক্সিকিউট' ব্যবহারের চেয়ে আমার কাছে ভাল লাগে sounds
ফ্রেলাউ

এটি __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

Sensকমত্যটি এর জন্য অভিধান ব্যবহার করা - অন্যান্য উত্তরগুলি দেখুন। এটি বেশিরভাগ ক্ষেত্রেই এটি একটি ভাল ধারণা, তবে এর থেকে অনেকগুলি দিক উত্থাপিত হয়:

  • আপনি নিজেই এই অভিধানটির জন্য দায়বদ্ধ থাকবেন, জঞ্জাল সংগ্রহ (ইন-ডিক ভেরিয়েবলগুলির) সহ etc. ইত্যাদি be
  • ভেরিয়েবল ভেরিয়েবলের জন্য কোনও স্থানীয়তা বা বিশ্বব্যাপীতা নেই, এটি অভিধানের বিশ্বতার উপর নির্ভর করে
  • আপনি যদি কোনও ভেরিয়েবলের নাম পরিবর্তন করতে চান তবে আপনাকে এটি ম্যানুয়ালি করতে হবে
  • তবে আপনি অনেক বেশি নমনীয়, যেমন
    • আপনি বিদ্যমান ভেরিয়েবলগুলি ওভাররাইট করার সিদ্ধান্ত নিতে পারেন বা ...
    • ... কনস্ট ভেরিয়েবলগুলি প্রয়োগ করতে বেছে নিন
    • বিভিন্ন ধরণের ওভাররাইটিংয়ে ব্যতিক্রম বাড়াতে
    • প্রভৃতি

বলেছিল, আমি একটি ভেরিয়েবল ভেরিয়েবল ম্যানেজার প্রয়োগ করেছি ক্লাস যা উপরোক্ত কিছু ধারণাগুলি সরবরাহ করে। এটি অজগর 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.৩ এ চেষ্টা করেছি, আপনি গ্লোবাল () বা ভার্স () ব্যবহার করতে পারেন

>>> 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.