【问题标题】:assign value to a variable using eval in a metaprogramming manner以元编程方式使用 eval 为变量赋值
【发布时间】:2020-10-05 17:19:12
【问题描述】:

我想以元编程方式使用 eval 为变量赋值。我的尝试如下所示:

sample = None
var_name = "sample"
value = 0
eval("{0} = {1}".format(var_name, value))

但是,我收到以下错误:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    eval("{0} = {1}".format(var_name, value))
  File "<string>", line 1
    sample = 0
           ^
SyntaxError: invalid syntax

您能解释一下我该怎么做吗?我认为可能存在像assign(var, val) 这样的较低级别的函数,并且使用eval 启用了这个赋值。但是我找不到这样的功能。

【问题讨论】:

  • Python 的 eval 函数计算表达式。它不执行语句。赋值是一个语句,而不是表达式。这解释了你遇到的问题。一般来说。使用 eval 进行全局更改是一个非常糟糕的主意。
  • exec 做你想做的事。
  • 但是无论你想做什么,请不要这样做。您正在程序中创建一个巨大的安全漏洞。无论您真正想要完成的是什么,都有更好、更安全的方法。
  • 嗯,我正在修改现有软件,为了保持向后兼容性并添加我的功能,使用元编程似乎是唯一的方法......
  • @orematasaburo 不,几乎可以肯定,使用evalexec 不是正确的方法。如果您确实描述了您的问题,我们也许可以为您指明正确的方向

标签: python eval metaprogramming


【解决方案1】:

改用exec

sample = None
var_name = "sample"
value = 0
exec("{0} = {1}".format(var_name, value))

eval 用于评估表达式,而不是赋值语句

【讨论】:

    【解决方案2】:

    exec 是否完成了你想做的事情?:

    sample = None
    var_name = "sample"
    value = 5
    exec(f"{var_name} = {value}")
    
    print(sample)
    

    输出:5

    【讨论】:

      【解决方案3】:

      如果你在一个函数之外,你可以使用

      globals()[varname] = value
      

      例子:

      >>> a
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      NameError: name 'a' is not defined
      >>> globals()['a'] = 5
      >>> a
      5
      

      在函数内部有locals(),但它只能从符号表中读取而不能更新,因此您应该像其他答案指出的那样使用eval()

      您也可以通过在对象上使用 setattr/hasattr/getattr 来作弊:

      >>> class Object:
      ...     pass
      ... 
      >>> obj = Object()
      >>> obj.a
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'Object' object has no attribute 'a'
      >>> setattr(obj, 'a', 3)
      >>> obj.a
      3
      

      【讨论】:

      • evalexec 都不会更新本地 sybol 表
      猜你喜欢
      • 2015-09-14
      • 1970-01-01
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 2017-07-01
      • 2013-11-11
      • 2013-02-25
      • 1970-01-01
      相关资源
      最近更新 更多