Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在函数中使用dir()作为默认参数_Python - Fatal编程技术网

Python 如何在函数中使用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_

我不知道我做错了什么。似乎我无法使用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_all_vars

那么-首先,发生了什么-

包含
def
语句的行仅运行一次,当包含函数的模块首次导入时(或在交互提示上)-无论如何,用作默认参数值的任何表达式都将一次性计算,其结果对象将保留为该参数的默认值

因此,将执行
dir()
调用,并保存包含示例函数的模块命名空间上的结果列表-a
dir
。(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)