3

背景:我正在制作一个 Ren'py 游戏。值为 Character()。是的,我知道在这种情况下这是一个愚蠢的想法。

我需要从存在于类范围之外的类中的输入字符串创建一个变量:

class Test:
    def __init__(self):
        self.dict = {} # used elsewhere to give the inputs for the function below.

    def create_global_var(self, variable, value):
        # the equivalent of exec("global {0}; {0} = {1}".format(str(variable), str(value)))
        # other functions in the class that require this.

Test().create_global_var("abc", "123") # hence abc = 123

我试过vars()[],globals()[variable] = value等,但它们根本不起作用(它们甚至没有定义任何东西)编辑:这是我的问题。

我知道以下内容也同样有效,但我希望变量在正确的范围内:

setattr(self.__class__, variable, value) # d.abc = 123, now. but incorrect scope.

如何在类中创建全局范围内的变量,使用字符串作为变量名,而不在 python 中使用属性或 exec?

是的,我会进行健全性检查。

4

2 回答 2

7

首先要做的事情:我们在 Python 中所谓的“全局”范围实际上是“模块”范围(从好的方面来说,它减少了使用全局变量的“邪恶”)。

然后,为了动态创建全局变量,虽然我仍然不明白为什么这比使用模块级字典更好,但只需执行以下操作:

globals()[variable] = value

这会在当前模块中创建一个变量。如果您需要在调用该方法的模块上创建一个模块变量,您可以使用以下命令从调用者框架中查看全局字典:

from inspect import currentframe
currentframe(1).f_globals[variable] = name

现在,这似乎特别无用,因为您可以创建一个具有动态名称的变量,但您不能动态访问它(除非再次使用全局字典)

即使在您的测试示例中,您也可以创建“abc”变量,将方法传递给字符串,但随后您必须使用硬编码的“abc”来访问它 - 语言本身旨在阻止这种情况(因此与 Javascript 不同,其中数组索引和对象属性是可互换的,而在 Python 中你有不同的映射对象)

我的建议是您使用模块级显式字典并将所有动态变量创建为键/值对:

names = {}
class Test(object):
    def __init__(self):
        self.dict = {} # used elsewhere to give the inputs for the function below.

    def create_global_var(self, variable, value):
         names[variable] = value

(附带说明,在 Pyhton 2 中总是从“对象”继承你的类)

于 2012-11-09T15:41:02.437 回答
2

你可以用setattr(__builtins__, 'abc', '123')这个。

请注意,这很可能是设计问题,您应该重新考虑设计。

于 2012-11-09T15:40:13.183 回答