【问题标题】:Execute script from string with accessing the variables?从字符串执行脚本并访问变量?
【发布时间】:2018-11-19 19:18:46
【问题描述】:

我有一个 python 脚本作为字符串,例如:

exec("sent = {'test': 1}")
global sent
print(sent)

我使用 exec 函数执行它,然后使用global python 命令访问该变量。这种方式在不使用类的情况下没有问题,但是当我在一个类中有相同的代码时,比如:

class example:
    def fun1(self):
        exec("sent = {'test': 1}")
        global sent
        print(sent)

v = example()
print(v.fun1())

我收到以下错误:

NameError: name 'sent' is not defined

【问题讨论】:

  • 尝试: exec("global sent;sent = {}") 。但尽量避免使用全局变量。
  • 我无法在字符串中添加“global”,因为它太长了
  • Ghanem:你的意思是它太长了? Python 中的字符串几乎可以是任意长度。
  • 这是一个数据集,有人用代码格式构建它..“虚拟方式”

标签: python python-3.x global-variables exec


【解决方案1】:

您没有传递全局字典进行修改。试试:

 exec("sent = {}",globals())

【讨论】:

  • 为了让问题更清楚,我将一个值附加到“sent”变量
  • 最初的问题是试图将'sent'初始化为一个空数组。这是这样做的。您还可以将“发送”设置为给定的字典,如修改后的问题:exec("sent = {'test': 1}",globals()) 或修改以前定义为全局的字典:exec( " my_global_dictionary['new_key'] = 'new_value'", global()) 但是添加第二个参数,对全局字典的引用至关重要。如果您不添加此 exec,则会创建一个全局字典 = {},在调用该函数后将其丢弃。
【解决方案2】:

您确实应该避免使用全局变量。无论如何,这里是如何做到这一点:

class example:
    def fun1(self):
#        globals sent  # Not needed in this special case.
        exec("sent = {}", globals())
        print('in fun1, "sent" is now', sent )


v = example()
print(v.fun1())  # Result will be None because fun1() doesn't return anything.
print('after call to fun1(), global "sent" is', sent)

输出:

in fun1, "sent" is now {}
None
after call to fun1(), global "sent" is {}

global 声明仅在函数或类方法中执行某些操作,即使这样,也仅在将全局变量的值设置为某个值时才需要。 然而,作为一种特殊情况,fun1() 方法中并不真正需要它,因为它在调用exec() 时显式传递了globals()(但不是单独的本地字典)。无论如何,最好还是放一个以便更清楚地了解发生了什么。

以这种方式使用exec() 在其documentation 中进行了解释,其中说:

如果只提供全局变量,则它必须是字典,它将用于全局变量和局部变量。

(强调我的)

这是一种避免在方法中引用全局变量的方法:

class example:
    def fun1(self):
        namespace = {}
        exec("sent = {}", namespace)
        sent = namespace['sent']  # Retrieve result.
        print('in fun1, "sent" is now', sent )
        return sent

v = example()
sent = v.fun1()
print('after calling fun1(), "sent" got set to', sent)

输出:

in fun1, "sent" is now {}
after calling fun1(), "sent" got set to {}

【讨论】:

  • 它不起作用,它打印“None .. 关于:“你真的应该避免使用全局变量”,在这种情况下有什么替代方法?
  • Ghanem:我认为它现在有效,对此感到抱歉。使用全局变量的替代方法取决于您正在做什么。最常见的方法是将它们作为参数传递给函数/方法(如果它们具有可变值)。另一个是通过returning 他们从函数/方法。即sent = v1.fun1()(假设您还在方法末尾放置了return sent 语句)。
猜你喜欢
  • 2021-12-02
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 2021-01-10
  • 2021-08-04
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
相关资源
最近更新 更多