python中的locals()字典在调试时是只读的吗?

发布于 2025-01-08 14:25:33 字数 1632 浏览 1 评论 0原文

我正在 python 中使用精彩的 sympy 来生成 ODE 系统的增强系统来计算各国对各国的敏感性。我的目标是优化 ODE 系统。如果我有一个 x1...x10 和参数 a1...a5 的系统,那么增强系统将具有 10+10*5 个状态。我的 sympy 代码生成额外的状态并将它们分配给变量 x1...x60。

后来我使用 numpy 中的集成来解决增强系统。所以我必须编写一个返回 ODE 系统的 rhs() 的函数 - 类似于 这段代码 (如果你们中的一些人是 numpy 的开发人员,请更正 Two_springs.py 第 29 行中的错误 - m2 丢失)。

我的问题是:我希望在函数内部动态分配变量 x1...x_end (状态总数将根据我用于灵敏度的参数数量而变化)。当我发现 python 中内置的 locals() 函数时,我很兴奋。来自这篇文章 我认为这应该可行:

def test_l(w, t):
for ii in range(len(w)):
    varStr="a%d" % (ii)
    locals()[varStr]=w[ii]
return a1*t+a0
w0 = [1.0, 1.0]
t0 = 1.0
f_x=test_l(w0, t0)
print "func res-> %1.4f\n" % (f_x)

运行脚本我得到全局名称'a1'未定义。后来我发现 localst() 实际上是只读。让我困惑的是,如果我在 ipython 中使用 pde on 调试函数,那么变量 a1a0 > 实际上存在于函数内部...在“pdb on”的情况下运行代码我仍然收到错误,程序执行在 return() 处停止,但 a1 和 a0 实际上存在于函数的内部工作区。

ipdb> a1 1.0

ipdb> a0 1.0

为什么 locals() 是只读的,但使用 pdb 调试时,字典实际上可以更改?

PS:我是这样解决我的问题的:

 for ii in range(len(w)):
    #varStr="a%d" % (ii)
    #locals()[varStr]=w[ii]
    varStr="a%d=w[%d]" % (ii, ii)
    exec(varStr)
 return a1*t+a0

I am using the wonderful sympy in python to generate the augmented system of an ODE system to calculate the forward sensitivities of the states with respect to to states. My goal is to optimize a system of ODEs. If I have a system of x1...x10 and parameters a1...a5, then the augmented system would have 10+10*5 states. The sympy code I have generates the extra states and assigns them to variables x1...x60.

Later I am using integration in numpy to solve the augmented system. So I have to code a function that returns a the rhs() of the ODE-system - something like this code (if some of you out there is developer at numpy, please correct the bug in two_springs.py, line 29 - m2 is missing).

And my my problem: I want inside a function to assign the variables x1...x_end dynamically (the total number of states would change depending how many parameter I use for the sensitivities). I was thrilled then I found the built-in locals() function in python. From this post I thought this should work:

def test_l(w, t):
for ii in range(len(w)):
    varStr="a%d" % (ii)
    locals()[varStr]=w[ii]
return a1*t+a0
w0 = [1.0, 1.0]
t0 = 1.0
f_x=test_l(w0, t0)
print "func res-> %1.4f\n" % (f_x)

Running the script I am getting global name 'a1' is not defined. Later I found out that localst() is actually read only. This what confuses me is that if I debug the function with pde on in ipython, then the variables a1 and a0 actually exist inside the function... Running the code with 'pdb on' I am still getting an error, the program execution stops at the return(), but a1 and a0 actually exist in the function's workspace.

ipdb> a1
1.0

ipdb> a0
1.0

How comes that locals() is read-only, but when debugging with pdb the dictionay can be actually changed?

PS: I solved my problem in this way:

 for ii in range(len(w)):
    #varStr="a%d" % (ii)
    #locals()[varStr]=w[ii]
    varStr="a%d=w[%d]" % (ii, ii)
    exec(varStr)
 return a1*t+a0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

儭儭莪哋寶赑 2025-01-15 14:25:33

首先我要声明我对同情一无所知。我只是浏览了文档以回应您的评论,即您无法从字典创建符号...

locals() 正如您所建议的,是只读的。引用 python 文档:

注意此词典的内容不应修改;变化
可能不会影响使用的局部变量和自由变量的值
口译员。

我认为这意味着在任何情况下修改它都是不可预测的。因此,如果变量在调试期间处于活动状态,我假设在这些情况下垃圾收集存在差异。或者……不可预测。

至于sympy中的符号变量。它们似乎只是一个标准的 python 类。这不能从您动态创建的字典创建 Symbol 对象吗?

from sympy import *
myVars = {'a1':1.0, 'a2':1.0 }
print [Symbol(k) for k in myVars.iterkeys()]
# [a₁, a₂]

如果没有更多关于 sympy 的知识,我不完全确定这些值的用法,但我确信您可以使用类似的方法做任何您需要的事情。动态变量名的需求几乎总是可以通过其他方法来解决。

Let me start by disclaiming that I know nothing about sympy. I only took a glance at the docs in response to your comment that you couldn't create Symbols from a dictionary...

locals(), as you suggested, is read-only. Quoting from the python docs:

Note The contents of this dictionary should not be modified; changes
may not affect the values of local and free variables used by the
interpreter.

I take that to mean that modifying it under any circumstance would be unpredictable. Thus, if the variables are alive during your debugging, I'm assuming there is a difference in the garbage collection under those circumstances. Or... unpredictability.

As for the Symbolic variables in sympy. They just seem to be a standard python class. Wouldn't this work to create Symbol objects from a dict that you dynamically created?

from sympy import *
myVars = {'a1':1.0, 'a2':1.0 }
print [Symbol(k) for k in myVars.iterkeys()]
# [a₁, a₂]

I'm not entirely sure about the usage of the values without more knowledge of sympy, but I'm sure you can do whatever you need to using a similar approach. The need for dynamic variable names on the fly can pretty much always be solved with some other approach.

離人涙 2025-01-15 14:25:33

jdi 提到的 Python 文档中针对写入 locals() 发出警告的原因是,大多数时候,您在 locals() 中更改的内容不会得到传播回实际的局部变量。这是因为当地人可能来自多个地方。 locals() 首先是一个函数而不是字典的原因是,可以有一些代码将所有局部变量从它们存在的位置收集到它们所在的一个位置。可以方便地阅读。

有时写入由 locals() 返回的字典是有效的。如果您在函数中的任何位置包含 exec 语句,即使它从未执行(即在 return 语句之后),写入 locals() 会起作用。然而,局部变量将比其他情况慢,因为当 Python 在“编译”时不知道所有变量的名称时,它无法使用“快速”操作码通过索引访问局部变量。局部变量。

def foo(val):    # circuitously returns value passed in
    locals["b"] = val
    return b
    exec ""

另外,您会发现闭包(内部函数和外部函数之间共享变量)不起作用。

def foo(a):   # can't define this function
    def bar():
       return a
    return bar
    exec ""

我相信当跟踪函数处于活动状态时,Python 解释器还会使用 locals() 发挥一些额外的作用。

这都是 CPython 特有的; Jython 和 IronPython 的行为可能有所不同。

The reason for the warning in the Python documentation against writing to locals() that jdi mentions is that most of the time, things you change in locals() don't get propagated back to the actual local variables. That's because locals can come from more than one place. The reason locals() is a function in the first place, rather than a dictionary, is so that there can be some code that gathers all the local variables from the places where they exist into one place where they can be read conveniently.

There are occasions when writing to the dictionary returned by locals() works. If you include an exec statement anywhere in your function, even if it's never executed (i.e. is after a return statement), writing to locals() will work. However, local variables will then be slower than otherwise because Python can't use the "fast" opcodes to access local variables by index when it doesn't know at "compile" time the names of all the local variables.

def foo(val):    # circuitously returns value passed in
    locals["b"] = val
    return b
    exec ""

Also, you will then find that closures (sharing of variables between an inner and outer function) don't work.

def foo(a):   # can't define this function
    def bar():
       return a
    return bar
    exec ""

I believe that the Python interpreter also does some extra magic with locals() while a trace function is active.

This is all specific to CPython; Jython and IronPython probably behave differently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文