Python'da değişken değişkenleri nasıl başarabilirim?
İşte ayrıntılı bir manuel giriş, örneğin: Değişken değişkenler
Bunun genel olarak kötü bir fikir olduğunu duydum ve Python'da bir güvenlik deliği. Bu doğru mu?
Python'da değişken değişkenleri nasıl başarabilirim?
İşte ayrıntılı bir manuel giriş, örneğin: Değişken değişkenler
Bunun genel olarak kötü bir fikir olduğunu duydum ve Python'da bir güvenlik deliği. Bu doğru mu?
Yanıtlar:
Bunu yapmak için sözlükleri kullanabilirsiniz . Sözlükler, anahtar ve değer depolarıdır.
>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2
Güvenlik riski olmadan değişken değişkenlerin etkisini elde etmek için değişken anahtar adlarını kullanabilirsiniz.
>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'
Gibi bir şey yapmayı düşündüğünüz durumlar için
var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...
bir liste bir diktenden daha uygun olabilir. Liste, tamsayı dizinleriyle sıralı bir nesne dizisini temsil eder:
lst = ['foo', 'bar', 'baz']
print(lst[1]) # prints bar, because indices start at 0
lst.append('potatoes') # lst is now ['foo', 'bar', 'baz', 'potatoes']
Listeleri endeksi sırayla, içinde yinelemeyi desteklemesi nedeniyle sipariş dizileri için, liste, tamsayı tuşlarıyla dicts daha kullanışlıdır dilimleme , append
bir dict ile garip anahtar yönetimini gerektirir ve diğer operasyonlar.
getattr
Nesne üzerinde ada göre bir öznitelik almak için yerleşik işlevi kullanın. Adı gerektiği gibi değiştirin.
obj.spam = 'eggs'
name = 'spam'
getattr(obj, name) # returns 'eggs'
İyi bir fikir değil. Genel bir değişkene erişiyorsanız kullanabilirsiniz globals()
.
>>> a = 10
>>> globals()['a']
10
Yerel kapsamdaki bir değişkene erişmek istiyorsanız kullanabilirsiniz locals()
, ancak döndürülen dikte değer atayamazsınız.
Daha iyi bir çözüm , getattr
değişkenlerinizi bir sözlükte kullanmak veya saklamak ve daha sonra ada göre erişmek.
Değişken değişkenleri kullanmak istediğinizde, muhtemelen bir sözlük kullanmak daha iyidir. Yani yazmak yerine
$foo = "bar"
$$foo = "baz"
Sen yaz
mydict = {}
foo = "bar"
mydict[foo] = "baz"
Bu şekilde daha önce var olan değişkenlerin (güvenlik yönüdür) üzerine yanlışlıkla yazmazsınız ve farklı "ad alanlarınız" olabilir.
Yeni kodlayıcılar bazen şöyle kod yazarlar:
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)
...
Kodlayıcı daha sonra adlandırılmış değişkenlerden oluşan bir yığınla bırakılır, kodlama çabası O ( m * n ) 'dir, burada m , adlandırılmış değişkenlerin sayısıdır ve n , bu değişken grubuna erişilmesi gereken sayıdır (oluşturma dahil) ). Daha zekice başlayanlar, bu satırların her birindeki tek farkın, bir kurala göre değişen ve bir döngü kullanmaya karar veren bir sayı olduğunu gözlemler. Ancak, bu değişken adlarının dinamik olarak nasıl oluşturulacağı konusunda takılırlar ve şöyle bir şey deneyebilirler:
for i in range(10):
my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)
Yakında bunun işe yaramadığını fark ettiler.
Program keyfi değişken "adlar" gerektiriyorsa, diğer cevaplarda açıklandığı gibi sözlük en iyi seçimdir. Bununla birlikte, sadece çok sayıda değişken oluşturmaya çalışıyorsanız ve bunlara bir tamsayı dizisiyle başvurmak sakıncası yoksa, muhtemelen bir list
. Bu, özellikle verileriniz günlük sıcaklık okumaları, haftalık sınav puanları veya grafik widget'ları gibi homojense doğrudur.
Bu aşağıdaki gibi monte edilebilir:
my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))
Bu list
, bir anlayışla tek bir satırda da oluşturulabilir:
my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
Her iki durumda da sonuç list
, ilk öğeye erişilen my_calculator.buttons[0]
, bir sonraki öğeyle my_calculator.buttons[1]
vb. Yerleştirilmiş olarak doldurulur . "Base" değişken adı, adı olur list
ve değişken tanımlayıcı ona erişmek için kullanılır.
Son olarak, diğer veri yapılarını da unutmayın set
- bu bir sözlüğe benzer, ancak her "ad" ın kendisine bir değeri eklenmez. Nesnelerin bir "çantasına" ihtiyacınız varsa, bu harika bir seçim olabilir. Bunun gibi bir şey yerine:
keyword_1 = 'apple'
keyword_2 = 'banana'
if query == keyword_1 or query == keyword_2:
print('Match.')
Buna sahip olacaksınız:
keywords = {'apple', 'banana'}
if query in keywords:
print('Match.')
Bir kullanma list
benzer nesnelerin bir dizi, bir için set
bir isteğe bağlı olarak sipariş nesnelerin torba veya bir için dict
ilişkili değerlerin adları için bir torba.
Sözlük yerine, namedtuple
erişimi kolaylaştıran koleksiyon modülünden de kullanabilirsiniz .
Örneğin:
# 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)
Herhangi bir nesne kullanmak istemiyorsanız, yine de setattr()
geçerli modülünüzün içinde kullanabilirsiniz :
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__
Ancak bu değişkenle çalışmaz . Dinamik olarak herhangi bir genel değişken oluşturmak için genel bir mekanizma olup olmadığını merak ediyorum .
globals()
bunu yapabilir
SimpleNamespace
Sınıf ile yeni özelliklerini oluşturmak için kullanılabilir setattr
, ya da alt sınıf SimpleNamespace
ve yeni özellik adları (değişkenler) eklemek için Kendi işlevi oluşturun.
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a
Soruyu cevaplıyorum: Bir dize adı verilen bir değişkenin değeri nasıl alınır? ve bu soruya bağlantı içeren bir kopya olarak kapatılır.
Söz konusu değişkenler bir nesne (örneğin bir sınıfın bir parçası) bir parçası olan, o zaman bazı yararlı fonksiyonlar tam olarak elde etmek için hasattr
, getattr
ve setattr
.
Yani örneğin:
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)
Sonra şunları yapabilirsiniz:
v = Variables()
v.get_var("foo")
"İnitial_variable"
v.create_new_var(v.foo,"is actually not initial")
v.initial_variable
"aslında ilk değil"
kullanım globals()
Sen küresel kapsama aslında atama değişkenler dinamik, örneğin, bir genel kapsamına ulaşılabilir 10 değişkenleri istersem i_1
, i_2
... i_10
:
for i in range(10):
globals()['i_{}'.format(i)] = 'a'
Bu, bu 10 değişkenin tümüne 'a' atayacaktır, elbette değeri dinamik olarak da değiştirebilirsiniz. Bu değişkenlerin tümüne şimdi global olarak bildirilen diğer değişkenler gibi erişilebilir:
>>> i_5
'a'
Bu davranışı sağlamak için globals()
yerleşik yöntemi kullanmanız gerekir :
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
Fikir birliği bunun için bir sözlük kullanmaktır - diğer cevaplara bakınız. Bu, çoğu durum için iyi bir fikirdir, ancak bundan kaynaklanan birçok yön vardır:
Bununla birlikte, yukarıdaki fikirlerden bazılarını sağlayan bir değişken değişkenleri yönetici- sınıfı uyguladım . Python 2 ve 3 için çalışır.
Sen kullanmak istiyorum sınıfını böyle:
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'])
Yalnızca aynı türde değişkenlerin üzerine yazmaya izin vermek istiyorsanız:
myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)
Ben hem python 3.7.3 denedim, sen globals () veya vars () kullanabilirsiniz
>>> 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'
Herhangi bir değişken kümesi de bir sınıfa sarılabilir. Yerleşik sözlüğe doğrudan __dict__ özniteliği aracılığıyla erişilerek çalışma zamanında sınıf örneğine "değişken" değişkenler eklenebilir.
Aşağıdaki kod, inşaat sırasında örneğine değişkenler (bu durumda öznitelikler) ekleyen Değişkenler sınıfını tanımlar. Değişken adları belirtilen bir listeden alınır (örneğin, program kodu tarafından oluşturulmuş olabilir):
# 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