【问题标题】:Unpacking Sympy variables from dictionary从字典中解包 Sympy 变量
【发布时间】:2016-06-23 17:40:32
【问题描述】:

我正在编写一个程序来为我的微观经济学课做一些计算。由于根据给定的问题有一些工作方式,我创建了一个类。该类从命令行解析实用程序函数和“模式”,并根据模式调用一个或另一个函数。 由于每个函数都使用相同的变量,我在__init__() 中启动它们:

self.x = x = Symbol('x')  # Variables are initiated
self.y = y = Symbol('y')
self.Px, self.Py, self.m = Px, Py, m = Symbol('Px'), Symbol('Py'), Symbol('m')

我需要一个本地定义来成功处理该函数。通过sympify() 启动函数后,我将其保存为实例变量:

self.function = sympify(args.U) 

现在我需要将变量x,yPx,Py,m 传递给不同的函数。这就是我遇到问题的地方。因为我想要一个本地定义,所以我可以简单地 x=self.x 使用所有变量。我需要在每段不可持续的代码中重复这一点。另一种选择是将所有变量作为参数传递。

但是由于我使用字典来根据模式选择要调用的函数,这意味着我必须为每个函数传递相同的参数,无论我是否使用它们。

所以我决定创建一个字典,例如:

variables = {          #A dictionary of variables is initiated
        'x':self.x,
        'y':self.y,
        'Px':self.Px,
        'Py':self.Py,
        'm':self.m
        }

在我将变量声明为 sympy Symbols 后启动此字典。我想要的是把这本字典以解包的形式传递给每个函数。这样我只需要**kwargs 作为参数,我可以使用我想要的变量。

我想要的是这样的:

a = 3
arggs = {'a' = a}
def f(**kwargs):return a+1
f(**args)

这将返回 4。但是,当我将字典作为参数传递时,我得到一个未定义的“x”或“y”变量错误。这不可能是范围问题,因为所有实例的所有变量都已启动。

这是我调用该函数的代码:

 self.approaches[self.identification][0](**self.variables)
 def default(self, **kwargs):
     solutions = dict()
     self.MRS = S(self.function.diff(x) / self.function.diff(y))   # This line provokes the exception

我的错误是什么?

PS:有些信息可能不清楚。英语不是我的主要语言。提前道歉。

【问题讨论】:

    标签: python function dictionary arguments sympy


    【解决方案1】:

    不幸的是,Python 并不是这样工作的。当您使用**kwargs 时,此分配的唯一变量是变量kwargs,它是关键字参数的字典。通常,由于局部命名空间的工作方式,没有简单的方法将名称注入函数的本地命名空间。有很多方法可以做到这一点,但它们相当老套。

    使变量可用而不必每次都定义它们的最简单方法是在模块级别定义它们。一般来说,这是一种不好的做法(它确实确实属于该类),但由于 SymPy 符号是不可变的,并且完全由它们的名称定义(以及假设,如果你设置了任何),它就可以了设置

    Px, Py, m = symbols("Px Py m")
    

    在模块级别(即,在您的类定义之上),因为即使某些其他函数定义了自己的 Symbol("Px"),SymPy 也会认为它等于您之前定义的 Px

    一般来说,你可以用这种方式快速和松散地使用不可变对象(并且所有 SymPy 对象都是不可变的),因为不可变对象是否被第二个相等的对象替换并不重要。比如说,如果你有一个列表(一个可变容器),这将很重要,因为如果它是在模块级别、类级别和实例级别定义的,它会产生很大的不同。

    【讨论】:

    • 对于未知的指定数量的变量,从 x、y、z 到 m_g 或 v_B 等普通符号,这样做有什么“hacky”方式?
    • @imranal 之所以骇人听闻是因为在 Python 中,本地命名空间(函数的命名空间)是静态确定的。所以动态定义变量是没有意义的,因为你总是知道函数何时被编译,而函数中使用了哪些变量名。全局(模块级)命名空间不是这样工作的,实际上将变量名注入globals() 非常容易(SymPy var 函数会自动执行此操作)。但同样,如果您在脚本中静态使用某些特定变量,那么只需准确定义这些变量。
    猜你喜欢
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    相关资源
    最近更新 更多