全局变量不工作python

时间:2016-08-23 20:11:30

标签: python class python-3.x input global-variables

你好开发者,

我正在编写代码,该代码接受用户输入并根据输入初始化类,如下面的示例代码所示:

class X:
    def __init__(self):
       return

    def run(self):
       print("i am X")

def func1(cls):
    exec("global " + cls.lower())
    exec(cls.lower() + " = " + cls + "()")

def func2(mode_to_set):
    exec(mode_to_set.lower() + ".run()")

但是当我运行这样的代码时:

func1('X')
func2('X')

我一直收到这个错误:

Traceback (most recent call last):
  File "/Users/noahchalifour/Desktop/test.py", line 16, in <module>
    func2('X')
  File "/Users/noahchalifour/Desktop/test.py", line 13, in func2
    exec(mode_to_set.lower() + ".run()")
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined

任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:1)

基于用户输入实例化类的更好方法是使用&#34;工厂模式&#34;:

http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Factory.html

基本上,您创建了一个类,其目的是基于值创建其他类。有些人可能会发现过度杀伤,所以你也可以使用一个根据输入创建类的函数。

无论你做什么,现在的方式,使用exec运行原始的用户输入字符串,是个坏主意。最好的情况是,它引入了几乎不可能跟踪的新错误,因为它们实际上并未记录在任何地方。在最糟糕的情况下,用户以某种方式找到了将字符串发送到函数的方法,你几乎已经破坏了你所希望的任何安全性。

基本上&#34; exec&#34;通常应该是最后的手段。通常有更优雅和安全的方法来解决问题。

答案 1 :(得分:0)

似乎你最好让func2实例化运行该方法:

def func2(mode_to_set):
    globals()[mode_to_set]().run()

通过这种方式,您在全局命名空间中没有一大堆不受欢迎的错误,并且您最终不会执行不受信任的exec。此外,exec函数内的global语句不起作用(如您所见)... exec是一种执行字符串的方式,就像它是代码一样。 不是将动态创建的语句放入当前函数的方法。

答案 2 :(得分:0)

字典,词典,词典。您的程序应该保持对执行代码的控制,而不是让用户动态构造新代码。

classes = {'X': X}
instances = {}

def func1(cls):
    var = cls.lower()
    instances[var] = classes[cls]()

def func2(mode_to_set):
    instances[mode_to_set.lower()].run()

func1('X')
func2('X')

唯一的区别是你没有名为x的全局变量;你有一个全球字典,其中包含一个引用你的实例的密钥x