gpt4 book ai didi

How do I create variable variables?(如何创建变量变量?)

转载 作者:bug小助手 更新时间:2023-10-28 20:45:15 28 4
gpt4 key购买 nike



I know that some other languages, such as PHP, support a concept of "variable variable names" - that is, the contents of a string can be used as part of a variable name.

我知道其他一些语言,如PHP,支持“变量变量名”的概念--即,字符串的内容可以用作变量名的一部分。


I heard that this is a bad idea in general, but I think it would solve some problems I have in my Python code.

我听说总的来说这不是一个好主意,但我认为它可以解决我在Python代码中遇到的一些问题。


Is it possible to do something like this in Python? What can go wrong?

有没有可能用Python语言做这样的事情?会出什么问题呢?




If you are just trying to look up an existing variable by its name, see How can I select a variable by (string) name?. However, first consider whether you can reorganize the code to avoid that need, following the advice in this question.

如果您只是尝试按名称查找现有变量,请参见How Can I Sect a Variable By(字符串)Name?但是,请首先考虑是否可以按照此问题中的建议重新组织代码以避免这种需要。


更多回答

it's the maintainance and debugging aspects that cause the horror. Imagine trying to find out where variable 'foo' changed when there's no place in your code where you actually change 'foo'. Imagine further that it's someone else's code that you have to maintain... OK, you can go to your happy place now.

造成这种恐惧的是维护和调试方面。想象一下,当您的代码中没有实际更改‘foo’的地方时,试图找出变量‘foo’的更改位置。再想像一下,你必须维护的是别人的代码……好了,你现在可以去你快乐的地方了。

A further pitfall that hasn't been mentioned so far is if such a dynamically-created variable has the same name as a variable used in your logic. You essentially open up your software as a hostage to the input it is given.

到目前为止还没有提到的另一个缺陷是,如果这样一个动态创建的变量与您的逻辑中使用的变量同名。从本质上讲,你开放你的软件,作为它所提供的输入的人质。

You can modify your global and local variables by accessing the underlying dictionaries for them; it's a horrible idea from a maintenance perspective ... but it can be done via globals().update() and locals().update() (or by saving the dict reference from either of those and using it like any other dictionary). NOT RECOMMENDED ... but you should know that it's possible.

您可以通过访问全局变量和局部变量的底层字典来修改它们;从维护的角度来看,这是一个可怕的想法……但是它可以通过global als().update()和local als().update()来完成(或者保存这两个字典中的字典引用并像使用任何其他字典一样使用它)。不推荐...但你应该知道这是有可能的。

@JimDennis actually, no it can't. Modifications to the dict returned by locals will not affect local namespaces in CPython. Which is another reason not to do it.

@JimDennis实际上,它不能。对本地返回的dict的修改不会影响CPython中的本地命名空间。这是不这么做的另一个原因。

@juanpa.arrivillaga: I had tried testing this in an IPython shell, but did so at the top level (where locals() behaves like globsls()). Redoing that test within a nested code (within the definition of a function) does show that I can't modify locals() from within that. As you say, the help for locals (3.7.6) does warn: "NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is implementation dependent and not covered by any backwards compatibility guarantees."

@juanpa.arrivilaga:我曾尝试在IPython外壳中测试这一点,但在顶层(本地变量()的行为类似于lobsls())进行了测试。在嵌套代码中(在函数的定义中)重新执行该测试确实表明,我不能从该代码中修改本地变量()。正如您所说,本地化帮助(3.7.6)确实警告:“注意:此词典的更新是否会影响本地作用域中的名称查找,反之亦然,这取决于实现,并且不包含任何向后兼容性保证。”

优秀答案推荐

You can use dictionaries to accomplish this. Dictionaries are stores of keys and values.

您可以使用词典来实现这一点。词典是键和值的存储。


>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'x': 1, 'y': 2, 'z': 3}
>>> dct["y"]
2

You can use variable key names to achieve the effect of variable variables without the security risk.

您可以使用变量密钥名称来实现变量的效果,而不存在安全风险。


>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'

For cases where you're thinking of doing something like

在某些情况下,您正在考虑做一些类似的事情


var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...

a list may be more appropriate than a dict. A list represents an ordered sequence of objects, with integer indices:

一份清单可能比一本词典更合适。列表表示对象的有序序列,具有整数索引:


lst = ['foo', 'bar', 'baz']
print(lst[1]) # prints bar, because indices start at 0
lst.append('potatoes') # lst is now ['foo', 'bar', 'baz', 'potatoes']

For ordered sequences, lists are more convenient than dicts with integer keys, because lists support iteration in index order, slicing, append, and other operations that would require awkward key management with a dict.

对于有序序列,列表比使用整型键的字典更方便,因为列表支持按索引顺序迭代、切片、追加和其他操作,这些操作需要使用字典进行笨拙的键管理。



Use the built-in getattr function to get an attribute on an object by name. Modify the name as needed.

使用内置的getattr函数按名称获取对象的属性。根据需要修改名称。



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


It's not a good idea. If you are accessing a global variable you can use globals().

这不是个好主意。如果要访问全局变量,则可以使用GLOBALS()。



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


If you want to access a variable in the local scope you can use locals(), but you cannot assign values to the returned dict.

如果要访问局部作用域中的变量,可以使用本地变量(),但不能为返回的dict赋值。



A better solution is to use getattr or store your variables in a dictionary and then access them by name.

更好的解决方案是使用getattr或将变量存储在字典中,然后按名称访问它们。



New coders sometimes write code like this:

新的程序员有时会编写这样的代码:



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)
...


The coder is then left with a pile of named variables, with a coding effort of O(m * n), where m is the number of named variables and n is the number of times that group of variables needs to be accessed (including creation). The more astute beginner observes that the only difference in each of those lines is a number that changes based on a rule, and decides to use a loop. However, they get stuck on how to dynamically create those variable names, and may try something like this:

然后,编码者得到一堆命名变量,编码工作量为O(m*n),其中m是命名变量的数量,n是该变量组需要被访问(包括创建)的次数。更精明的初学者注意到,每一行中唯一的区别是根据规则变化的数字,并决定使用循环。然而,他们在如何动态创建这些变量名称方面遇到了困难,可能会尝试这样的操作:



for i in range(10):
my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)


They soon find that this does not work.

他们很快就发现这是行不通的。



If the program requires arbitrary variable "names," a dictionary is the best choice, as explained in other answers. However, if you're simply trying to create many variables and you don't mind referring to them with a sequence of integers, you're probably looking for a list. This is particularly true if your data are homogeneous, such as daily temperature readings, weekly quiz scores, or a grid of graphical widgets.

如果程序需要任意变量“名称”,词典是最佳选择,正如其他答案中所解释的那样。然而,如果您只是试图创建许多变量,并且您不介意用一系列整数引用它们,那么您可能正在寻找一个列表。如果您的数据是同质的,例如每天的温度读数、每周的测验成绩或图形小部件的网格,这一点尤其正确。



This can be assembled as follows:

它可以按如下方式组装:



my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))


This list can also be created in one line with a comprehension:

此列表也可以一行创建,并具有以下理解:



my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]


The result in either case is a populated list, with the first element accessed with my_calculator.buttons[0], the next with my_calculator.buttons[1], and so on. The "base" variable name becomes the name of the list and the varying identifier is used to access it.

在任何一种情况下,结果都是一个填充的列表,第一个元素用my_culator.Button[0]访问,下一个元素用my_culator.Button[1]访问,依此类推。“base”变量名成为列表的名称,并使用可变标识符来访问它。



Finally, don't forget other data structures, such as the set - this is similar to a dictionary, except that each "name" doesn't have a value attached to it. If you simply need a "bag" of objects, this can be a great choice. Instead of something like this:

最后,不要忘记其他数据结构,比如集合--这类似于字典,不同的是每个“名称”都没有值。如果你只是需要一袋物品,这可能是一个很好的选择。而不是这样的东西:



keyword_1 = 'apple'
keyword_2 = 'banana'

if query == keyword_1 or query == keyword_2:
print('Match.')


You will have this:

你会得到这个:



keywords = {'apple', 'banana'}
if query in keywords:
print('Match.')


Use a list for a sequence of similar objects, a set for an arbitrarily-ordered bag of objects, or a dict for a bag of names with associated values.

对相似对象的序列使用列表,对任意排序的对象包使用集合,对具有关联值的名称包使用字典。



Whenever you want to use variable variables, it's probably better to use a dictionary. So instead of writing

当你想使用可变变量时,最好使用字典。所以我没有写



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


you write

你写



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


This way you won't accidentally overwrite previously existing variables (which is the security aspect) and you can have different "namespaces".

这样,您就不会意外地覆盖以前存在的变量(这是安全方面的问题),并且您可以拥有不同的“名称空间”。



Use globals() (disclaimer: this is a bad practice, but is the most straightforward answer to your question, please use other data structure as in the accepted answer).

使用GLOBALS()(免责声明:这是一种糟糕的做法,但这是对您的问题的最直接的回答,请使用其他数据结构,就像在公认的答案中一样)。


You can actually assign variables to global scope dynamically, for instance, if you want 10 variables that can be accessed on a global scope i_1, i_2 ... i_10:

实际上,您可以将变量动态分配给全局作用域,例如,如果您希望在全局作用域I_1、I_2上访问10个变量...I_10:


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

This will assign 'a' to all of these 10 variables, of course you can change the value dynamically as well. All of these variables can be accessed now like other globally declared variable:

这将为所有这10个变量分配‘a’,当然您也可以动态更改该值。现在可以像访问其他全局声明的变量一样访问所有这些变量:


>>> i_5
'a'


Instead of a dictionary you can also use namedtuple from the collections module, which makes access easier.

您还可以使用集合模块中的命名元组来代替字典,这使得访问更加容易。


For example:

例如:


# using dictionary
variables = {}
variables["first"] = 34
variables["second"] = 45
print(variables["first"], variables["second"])

# using namedtuple
Variables = namedtuple('Variables', ['first', 'second'])
v = Variables(34, 45)
print(v.first, v.second)


The SimpleNamespace class could be used to create new attributes with setattr, or subclass SimpleNamespace and create your own function to add new attribute names (variables).

SimpleNamespace类可用于创建带有setattr的新属性,或子类SimpleNamesspace并创建您自己的函数来添加新的属性名称(变量)。



from types import SimpleNamespace

variables = {"b":"B","c":"C"}
a = SimpleNamespace(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a


If you don't want to use any object, you can still use setattr() inside your current module:

如果不想使用任何对象,仍可以在当前模块中使用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


Variable variables in Python


"""
<?php
$a = 'hello';
$e = 'wow'
?>
<?php
$$a = 'world';
?>
<?php
echo "$a ${$a}\n";
echo "$a ${$a[1]}\n";
?>
<?php
echo "$a $hello";
?>
"""

a = 'hello' #<?php $a = 'hello'; ?>
e = 'wow' #<?php $e = 'wow'; ?>
vars()[a] = 'world' #<?php $$a = 'world'; ?>
print(a, vars()[a]) #<?php echo "$a ${$a}\n"; ?>
print(a, vars()[vars()['a'][1]]) #<?php echo "$a ${$a[1]}\n"; ?>
print(a, hello) #<?php echo "$a $hello"; ?>

Output:

输出:


hello world
hello wow
hello world



Using globals(), locals(), or vars() will produce the same results


#<?php $a = 'hello'; ?>
#<?php $e = 'wow'; ?>
#<?php $$a = 'world'; ?>
#<?php echo "$a ${$a}\n"; ?>
#<?php echo "$a ${$a[1]}\n"; ?>
#<?php echo "$a $hello"; ?>

print('locals():\n')
a = 'hello'
e = 'wow'
locals()[a] = 'world'
print(a, locals()[a])
print(a, locals()[locals()['a'][1]])
print(a, hello)

print('\n\nglobals():\n')
a = 'hello'
e = 'wow'
globals()[a] = 'world'
print(a, globals()[a])
print(a, globals()[globals()['a'][1]])
print(a, hello)

Output:

产出:


locals():

hello world
hello wow
hello world


globals():

hello world
hello wow
hello world



Bonus (creating variables from strings)


# Python 2.7.16 (default, Jul 13 2019, 16:01:51)
# [GCC 8.3.0] on linux2

Creating variables and unpacking tuple:


g = globals()
listB = []
for i in range(10):
g["num%s" % i] = i ** 10
listB.append("num{0}".format(i))

def printNum():
print "Printing num0 to num9:"
for i in range(10):
print "num%s = " % i,
print g["num%s" % i]

printNum()

listA = []
for i in range(10):
listA.append(i)

listA = tuple(listA)
print listA, '"Tuple to unpack"'

listB = str(str(listB).strip("[]").replace("'", "") + " = listA")

print listB

exec listB

printNum()

Output:

输出:


Printing num0 to num9:
num0 = 0
num1 = 1
num2 = 1024
num3 = 59049
num4 = 1048576
num5 = 9765625
num6 = 60466176
num7 = 282475249
num8 = 1073741824
num9 = 3486784401
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) "Tuple to unpack"
num0, num1, num2, num3, num4, num5, num6, num7, num8, num9 = listA
Printing num0 to num9:
num0 = 0
num1 = 1
num2 = 2
num3 = 3
num4 = 4
num5 = 5
num6 = 6
num7 = 7
num8 = 8
num9 = 9


You have to use globals() built in method to achieve that behaviour:

您必须使用内置方法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


I'm answering the question How to get the value of a variable given its name in a string?
which is closed as a duplicate with a link to this question. (Editor's note: It is now closed as a duplicate of How can I select a variable by (string) name?)

我要回答的问题是,如何在字符串中获取给定名称的变量的值?它作为带有指向此问题的链接的副本关闭。(编者按:它现在作为如何按(字符串)名称选择变量的副本关闭?)




If the variables in question are part of an object (part of a class for example) then some useful functions to achieve exactly that are hasattr, getattr, and setattr.

如果所讨论的变量是对象的一部分(例如类的一部分),那么可以使用一些有用的函数来实现这一点:hasattr、getattr和setattr。


So for example you can have:

例如,您可以拥有:


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

Then you can do:

然后,您可以执行以下操作:


>>> v = Variables()
>>> v.get_var("foo")
'initial_variable'

>>> v.create_new_var(v.foo, "is actually not initial")
>>> v.initial_variable
'is actually not initial'


I have tried both in python 3.7.3, you can use either globals() or vars()

我在Python3.7.3中都试过了,您可以使用global()或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'





Reference:

https://www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936

参考文献:https://www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936



The consensus is to use a dictionary for this - see the other answers. This is a good idea for most cases, however, there are many aspects arising from this:

人们的共识是使用词典来解释这一点--请看其他答案。对于大多数情况来说,这是一个好主意,然而,由此产生的许多方面:




  • you'll yourself be responsible for this dictionary, including garbage collection (of in-dict variables) etc.

  • there's either no locality or globality for variable variables, it depends on the globality of the dictionary

  • if you want to rename a variable name, you'll have to do it manually

  • however, you are much more flexible, e.g.


    • you can decide to overwrite existing variables or ...

    • ... choose to implement const variables

    • to raise an exception on overwriting for different types

    • etc.




That said, I've implemented a variable variables manager-class which provides some of the above ideas. It works for python 2 and 3.

也就是说,我已经实现了一个变量变量管理器类,它提供了上面的一些想法。它适用于Python 2和3。



You'd use the class like this:

您可以这样使用这个类:



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


If you wish to allow overwriting of variables with the same type only:

如果您希望仅允许覆盖相同类型的变量:



myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)


Any set of variables can also be wrapped up in a class.
"Variable" variables may be added to the class instance during runtime by directly accessing the built-in dictionary through __dict__ attribute.

任何一组变量也可以包装在一个类中。通过__dict__属性直接访问内置字典,可以在运行时将变量添加到类实例中。



The following code defines Variables class, which adds variables (in this case attributes) to its instance during the construction. Variable names are taken from a specified list (which, for example, could have been generated by program code):

下面的代码定义Variables类,它在构造期间将变量(在本例中为属性)添加到其实例中。变量名取自指定的列表(例如,它可能是由程序代码生成的):



# 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


It should be extremely risky...
but you can use exec():

这应该是非常危险的..。但您可以使用exec():


a = 'b=5'
exec(a)
c = b*2
print (c)

Result:
10

结果:10人



The setattr() method sets the value of the specified attribute of the specified object.

方法的作用是:设置指定对象的指定属性的值。


Syntax goes like this –

它是这样的-


setattr(object, name, value)
Example –

setattr(self,id,123)

which is equivalent to self.id = 123

相当于self.id=123


As you might have observed, setattr() expects an object to be passed along with the value to generate/modify a new attribute.

正如您可能已经注意到的,setattr()期望传递一个对象和值以生成/修改新属性。


We can use setattr() with a workaround to be able to use within modules. Here’ how –

我们可以将setattr()与变通方法一起使用,以便能够在模块中使用。这里是“如何--


import sys
x = "pikachu"
value = 46
thismodule = sys.modules[__name__]
setattr(thismodule, x, value)
print(pikachu)


TL;DR: Consider using eval()

Tl;dr:考虑使用eval()


I found this page because I was looking to do some simple template processing with python string functions (short of including a full blown template engine). I was searching for how to set local variables, and that's how I got here.

我之所以找到这个页面,是因为我希望使用python字符串函数(不包括完整的模板引擎)进行一些简单的模板处理。我一直在寻找如何设置局部变量,这就是我来到这里的原因。


My problem began with a simple template:

我的问题始于一个简单的模板:


Hello, {name}

The way I populated this template was this way:

我填充这个模板的方式是这样的:


def populate(template,variables):
return template.format(**variables)

And so this would work:

因此,这是可行的:


values = {
'name' : 'Stack Overflow'
}
my_template = "Hello, {name}"
print( populate( my_template , values ) )

# output
Hello, Stack Overflow

But then things went south fast. I tried a new template where I only wanted the first word:

但后来事情很快就变得糟糕起来。我尝试了一个新的模板,我只想要第一个词:


Now my template was this: "Hello, {name.split()[0]}" and this code got an error.

现在我的模板是:“Hello,{name.plit()[0]}”,而这段代码出现了错误。


values['name'] = "Stack Overflow"
my_template = "Hello, {name.split()[0]}"
print( populate( my_template , values )
# output (well, stderr)
AttributeError: 'str' object has no attribute 'split()'. Did you mean: 'split'?

And then I learned that the format function doesn't work the way I want it. You can't pass arbitrary code to it. You need to pass it formatting stuff. And so I tried a different solution. I coded populate to use eval and an f-string instead of format. An f-string (unlike format) allows for python code in the curly brace interpolation. So an f-string like this `f"Hello, {name.split()[0]}" does work. Let's just see the code for this small part (so you don't have to leave this post to figure out f-string):

然后我了解到格式功能不是以我想要的方式工作的。您不能将任意代码传递给它。您需要向它传递格式化内容。所以我尝试了一种不同的解决方案。我对Popate进行了编码,以使用val和f字符串而不是格式。F字符串(与格式不同)允许在大括号内插中使用python代码。因此,像这样的f字符串`f“Hello,{name.plit()[0]}”确实可以工作。让我们来看看这一小部分的代码(这样你就不必离开这篇文章来了解f-字符串):


name = "Stack Overflow"
print(f"Hello, {name.split()[0]}")
# Output:
Hello, Stack

Now I just had to use an f-string. So I used eval. My new populate is this:

现在我只需要用一根F弦。所以我用了eval。我的新成员是:


def populate(template,variables):
return eval(f'f"{template}"')

But when I ran the program again, I got this error:

但当我再次运行该程序时,我收到了这个错误:


NameError: name 'name' is not defined

I should point out that an f-string is able to populate the string with any global or local variable in scope. To fix my issue, I could change my template to "Hello, {variables['name']}" since variables is definitely in scope. This is really bad approach because now the template writer has to know about a the variables dictionary. Rather, I want to make every key available in the variables dictionary available to the template author, as I had before with format(**variables).

我应该指出的是,f字符串能够用作用域中的任何全局或局部变量填充字符串。要解决我的问题,我可以将我的模板更改为“Hello,{Variables[‘name’]}”,因为变量肯定在作用域中。这是一种非常糟糕的方法,因为现在模板编写者必须了解变量字典。相反,我希望使变量字典中的每个键都可供模板作者使用,就像我以前对Format(**变量)所做的那样。


To solve my problem, I wanted to set local variables based on the content of the variables dictionary passed to the populate() function.

为了解决我的问题,我想根据传递给Popate()函数的变量字典的内容来设置局部变量。


I tried this:

我试过这个:


locals() = variables

And that didn't work:

但这并没有奏效:


    locals() = variables
^^^^^^^^
SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='?

And then I tried this and this worked:

然后我试了试,这招奏效了:


def populate(template,variables):
for k,v in variables.items():
locals()[k] = v
return eval(f'f"{template}"')


values = {
'name' : 'Stack Overflow'
}
my_template = "Hello, {name.split()[0]}"
print( populate( my_template , values ) )

And so the first take away is that you can create local variables in a function (or globals for that matter) by setting a key value pair in the locals() dictionary.

因此,第一个好处是可以通过在LOCALS()字典中设置键值对,在函数(或全局变量)中创建局部变量。


In the case of eval, the second and third parameters allow you to pass in local and global variables, and so you could simplify the populate function to just this:

在val的情况下,第二个和第三个参数允许您传入局部变量和全局变量,因此您可以将填充函数简化为:


def populate(template,variables):
return eval(f'f"{template}"',variables)

The above is how I used eval to do f-string population (or simplistic template evaluation). But eval can also be used to provide variable variables.

以上就是我使用eval进行f字符串填充(或简单的模板计算)的方法。但是val也可以用来提供变量。


更多回答

locals().update({'new_local_var':'some local value'}) works just fine for me in Python 3.7.6; so I'm not sure what you mean when you say you cannot assign values through it.

locals().update('new_local_var':'some local value'})在Python 3.7.6中对我来说工作得很好;所以我不知道你说你不能通过它赋值是什么意思。

Given x = "foo" and locals()["x"] = "bar" using print x gives the output bar for Jython 2.5.2. This was tested with an On Demand Automation Script in maximo.

在给定x=“foo”和local()[“x”]=“bar”的情况下,使用print x可以得到Jython2.5.2的输出栏。这是通过Maximo中的随需应变自动化脚本进行测试的。

The documentation of locals() specifically says: "The contents of this dictionary should not be modified." (emphasis mine)

Locals()的文档明确表示:“本词典的内容不应修改。”(重点是我的)

@JimDennis`locals()`` provides a dictionary created to represent local variables. Updating it does not guarantee to update the actual local variables. In modern Python implementations it's more like a picture (showing the content) in a nice frame (a high-level dict) – drawing on the picture won't actually change the real thing.

@JimDennis`Locals()``提供了为表示局部变量而创建的字典。更新它并不能保证更新实际的局部变量。在现代的Python实现中,它更像是漂亮框架(高级词典)中的一张图片(显示内容)--在图片上绘制实际上不会改变真实的东西。

The reason it doesn't work, at least on CPython, is that CPython allocates a fixed size array for locals, and the size of said array is determined when the function is defined, not when its run, and can't be changed (access to true locals doesn't even use the name; the name is replaced with the index into the array at function compile time). locals() returns a true dict; within a function, that dict is made by loading names and associated values in the array when you call locals(), it won't see future changes. If it changes, you're at global or class scope (which use dict scopes).

它不起作用的原因是,至少在CPython上,CPython为本地变量分配了一个固定大小的数组,并且该数组的大小是在定义函数时确定的,而不是在函数运行时确定的,并且不能更改(对真正的本地变量的访问甚至不使用该名称;该名称在函数编译时被替换为数组中的索引)。Locals()返回一个真正的dict;在函数中,当您调用Locals()时,该dict是通过在数组中加载名称和关联值来进行的,它不会看到未来的更改。如果它发生变化,则处于全局或类作用域(使用DICT作用域)。

Keep in mind namedtuples are immutable so they're a bit different than simply dicts with dot notation. Having said that, both options promote good design principles and don't abuse the global namespace like half the answers in this thread do.

请记住,命名的元组是不变的,因此它们与使用点符号的简单口述略有不同。话虽如此,这两种选择都促进了良好的设计原则,并且不会像本文中的一半答案那样滥用全局命名空间。

This does not work with __dict__ variable however. I wonder if there is a general mechanism to create any global variable dynamically.

但是,这不适用于__dict__变量。我想知道是否有一种通用的机制来动态创建任何全局变量。

globals() can do this

GLOBAL()可以做到这一点

The vars and locals dicts can't be modified inside a function. And mutable global state is bad except maybe in the simplest scripts. So this only has limited usefulness.

不能在函数内部修改变量和局部变量DICT。而可变的全局状态是不好的,除非是在最简单的脚本中。因此,这只有有限的用处。

This raises a string, which is not allowed. TypeError: exceptions must derive from BaseException. But why bother with hasattr() and raise when you could just do getattr() unconditionally and let it raise AttributeError for you?

这会引发一个字符串,这是不允许的。TypeError:异常必须派生自BaseException。但是,当您可以无条件地执行getattr()并让它为您引发AttributeError时,为什么还要费心使用hasattr()和Raise呢?

This won't work inside a function. It's essentially equivalent to the safer locals()['b'] = 5 (which also won't work in a function).

这在函数内部不起作用。它本质上等同于更安全的LOCALS()[‘b’]=5(在函数中也不起作用)。

@benrg Do you know how to get around Rubens failed suggestion because I'm stuck with the same situation? I have a file containing a long list of variable assignments as a collective string. I need to turn them into python assignments but eval() and exec() both fails.

@benrg你知道如何绕过鲁本斯失败的建议,因为我陷入了同样的境地吗?我有一个文件,其中包含作为集合字符串的一长串变量赋值。我需要将它们转换为Python赋值,但val()和exec()都失败了。

It's easier to use globals().

使用GLOBAL()更容易。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com