Python:`locals()`作为默认函数参数

Python:`locals()`作为默认函数参数,python,python-2.7,Python,Python 2.7,假设我有一个模块PyFoo.py,它有一个函数bar。我希望bar打印与调用它的名称空间关联的所有局部变量 例如: #! /usr/bin/env python import PyFoo as pf var1 = 'hi' print locals() pf.bar() 最后两行将给出相同的输出。到目前为止,我已经尝试将bar定义为: def bar(x=locals): print x() def bar(x=locals()): print x 但两者都不起作用。第一个

假设我有一个模块
PyFoo.py
,它有一个函数
bar
。我希望
bar
打印与调用它的名称空间关联的所有局部变量

例如:

#! /usr/bin/env python
import PyFoo as pf
var1 = 'hi'
print locals()
pf.bar()
最后两行将给出相同的输出。到目前为止,我已经尝试将
bar
定义为:

def bar(x=locals):
    print x()

def bar(x=locals()):
    print x
但两者都不起作用。第一个结果是
bar
的名称空间的本地内容(我猜这是因为它是在计算的时候),第二个结果就像我传入了
globals
(我假设这是因为它是在
导入期间计算的)

是否有一种方法可以使
bar
的参数
x
的默认值成为名称空间中名为
bar
的所有变量

编辑2018-07-29:

正如已经指出的,给出的是XY问题;因此,我将给出具体情况

我准备的模块将允许用户创建表示数值问题不同方面的各种对象(例如各种拓扑定义、边界条件、本构模型等),并定义任何给定对象如何与任何其他对象交互。用户的想法是导入模块,定义他们需要的各种模型实体,然后调用一个函数,该函数将获取传递给它的所有对象,进行必要的调整以确保它们之间的功能,然后写出一个文件,将整个数值问题表示为一个文本文件

该模块具有一个函数
generate
,该函数接受数值问题的各个方面。所有参数的默认值都是空列表。如果传递了非空列表,则
generate
将使用这些实例生成完整的数值问题。如果一个参数是一个空列表,那么我希望它接受名称空间中名为
generate
的所有实例(然后我将解析出该参数的相应实例)

编辑2018-07-29:

很抱歉,我没有理解(我不是一个很强的程序员),但是我想我可能理解您所说的关于声明或注册实例的内容


根据我有限的理解,这可以通过在模块中创建某种类型的注册表数据集(如
列表
dict
)来实现,该数据集将在导入模块时创建,并且默认情况下,所有模块类都接受此注册表对象。在类初始化期间,可以将
self
附加到所述数据集,然后
generate
函数将注册表作为其中一个参数的默认值?

无法直接执行所需操作

只返回在任何名称空间中调用的局部变量。如您所见,您可以访问在定义时定义函数的名称空间,并且可以从函数中访问函数本身的名称空间,但是您不能访问任何其他名称空间

你可以间接地做你想做的…但这几乎肯定是个坏主意。至少这闻起来像是一个,不管你实际上想做什么,可能有更好的方法

但有时这是必要的,因此,如果您有以下情况之一:


想要了解调用者的局部变量的主要原因是为了某种调试或其他内省功能。而内省的方法几乎总是通过图书馆

在这种情况下,您要检查的是。调用函数将是调用堆栈上位于函数自身帧后面的第一帧

您可以获得原始堆栈帧:

inspect.currentframe().f_back
…或者您可以获得表示它的
FrameInfo

inspect.stack()[1]
inspect
文档顶部所述,框架对象的本地名称空间如下所示:

frame.f_locals
请注意,这与使用
局部变量
获取您自己的局部变量有着相同的注意事项:您得到的不是活动名称空间,而是一个映射,即使它是可变的,也不能用于修改名称空间(或者,更糟的是,在2.x中,可能会或可能不会不可预测地修改名称空间),这使得所有的单元格和自由变量都变成了它们的值,而不是它们的单元格引用


另外,请参阅文档中关于不必要地保持帧对象活动的重要警告(如果需要保留快照但不是所有引用,请调用它们的方法,但我认为这仅存在于3.x中)。

这不是好的做法。请不要这样做。您可以使用
inspect.stack
访问调用范围。但这看起来根本不是个好主意。这闻起来像个XY问题。你到底想做什么?我认为最好重新设计你的API,以便用户以某种方式声明或注册实例。但这可以在对象的构造函数中自动完成。如果您需要具有多个具有独立对象的上下文,而不是依赖本地名称空间来兼作上下文,则可以将其显式化(例如,传递到每个对象的构造函数中),但对于简单情况,可以使用默认的“当前上下文”。如果正在进行并发,“当前”可以是线程本地、异步循环本地,或者对于3.7,可以是
contextvars
。很像
十进制
。模块。另一个选项是Symphy使用的。大多数情况下,在构建您想要解决的问题时,您会将这些问题彼此关联起来,但求值函数通常需要一些额外的绑定或其他无法关联的东西。通常您手动传递它们,但对于交互式探索性工作,有时您只需要“一切”,如果其中包含一些您不应该忘记的内容,您可以处理错误,因为这都是通过传递
局部变量来实现的交互式操作(