Python 如何在函数中使用dir()作为默认参数
我不知道我做错了什么。似乎我无法使用dir()作为函数输入的默认参数Python 如何在函数中使用dir()作为默认参数,python,Python,我不知道我做错了什么。似乎我无法使用dir()作为函数输入的默认参数 def print_all_vars(arg=dir()): for i in arg: print(i) foo=1 如果我使用 print_all_vars() 给出输出 __builtins__ __cached__ __doc__ __file__ __loader__ __name__ __package__ __spec__ 但是 输出 __builtins__ foo print_
def print_all_vars(arg=dir()):
for i in arg:
print(i)
foo=1
如果我使用
print_all_vars()
给出输出
__builtins__
__cached__
__doc__
__file__
__loader__
__name__
__package__
__spec__
但是
输出
__builtins__
foo
print_all_vars
那么-首先,发生了什么- 包含
def
语句的行仅运行一次,当包含函数的模块首次导入时(或在交互提示上)-无论如何,用作默认参数值的任何表达式都将一次性计算,其结果对象将保留为该参数的默认值
因此,将执行dir()
调用,并保存包含示例函数的模块命名空间上的结果列表-adir
。(Python初学者最常见的相关错误是尝试将空列表或字典([]
或{}
)作为参数默认值:相同的列表或字典将在函数的生命周期内重复使用)
这就解释了为什么在输出中会看到一些值,如果从交互提示中使用dir
调用它,这些值将不会显示,例如\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
现在,你真正的问题是:
。。。我实际上是在尝试创建一个模拟MATLAB的save函数
将所有现有变量保存到可以
后来被召回——
因此,即使延迟执行dir()
,当只调用函数时,仍然会失败:它仍然会从定义函数的模块而不是调用方检索变量名
这样做的编码模式是:
def print_all_vars(arg=None):
if arg is None:
arg = dir()
...
(这是在函数体上强制使用字典空列表作为默认参数的最常用方法)
但即使这样,或者如果您将自己的变量名列表显式地传递给函数,您仍然只有一个字符串列表,而不是需要保存的Python对象
并且-如果您希望在默认情况下从调用者检索变量,那么使用此字符串列表有一个共同的问题:您需要能够访问调用者代码的名称空间,以便检索其中存在的变量名,然后检索其内容以便保存
在Python中知道“谁调用了你的函数”是一种高级的方法,我甚至不确定它是否能保证在所有Python实现中都能工作——但它肯定能在最常见的(cPython、pypypy、Jython)上工作,甚至可以在一些较小的实现(如Brython)上工作:
调用sys.\u getframe()
以检索当前正在执行的代码的框架对象(即函数本身中的代码),此框架对象将具有f\u back
属性,该属性指向调用函数的代码的框架对象。框架对象在其一侧引用代码的全局变量和局部变量,这些变量作为普通字典分别运行为f_globals
和f_locals
您可以根据需要在调用者代码中“保存”和“恢复”全局变量的内容,但不能使用纯Python代码更新局部变量
因此,只要在默认情况下列出调用方代码上的全局变量,就可以执行以下操作:
import sys
def print_all_vars(arg=None):
if arg is None:
arg = list(sys.get_frame.f_back.f_globals.keys())
print (arg)
能够正确地保存和恢复这些变量是另一个问题——正如您在注释中看到的,您可以使用pickle
来序列化许多Python对象——但是调用方名称空间将具有模块名称(例如math
np`,等等)这是无法正常处理的,因此您必须提供一种策略,通过对检索到的所有对象进行进一步的内省来检测、注释使用的模块,并恢复它们
无论如何,尝试这里的信息应该会让您找到想要的东西。默认参数中的表达式只执行一次,并与函数对象一起存储。并非每次通话都适用。您看到的是模块名称空间(函数在其中定义的模块中的全局变量)。@Lee88:dir()的dir()
到底是什么?你想要内省什么?如果你解释一下你想要完成什么,也许会更好。这听起来像是XY的问题。@Lee88:看到了吗then@Lee88您可能会感兴趣的是,哪个提供了“保存”解释器会话的功能,我想这就是您想要实现的。
import sys
def print_all_vars(arg=None):
if arg is None:
arg = list(sys.get_frame.f_back.f_globals.keys())
print (arg)