我遇到了一个很难解释的问题,因为涉及很多代码。所以归结为以下问题。
我正在尝试访问函数foo之外的列表xxx,但我得到了意想不到的结果。有人可以解释一下为什么吗?
这是我创建的用于显示问题的函数:
def foo(xxx = []):
if len(xxx) == 5:
return xxx
xxx += [1]
foo()
return xxx
如果我跑步
print foo()
我明白了
[1, 1, 1, 1, 1]
这正是我所期望的。
但我希望列表 xxx 可以在 foo 外部访问。所以,我正在做
xxx = []
print foo(xxx)
print xxx
现在我希望得到的列表xxx是
[1, 1, 1, 1, 1]
但是我想要的xxx是
[1]
这不是我所期望的。
有人可以解释一下为什么吗?是否可以在 foo 之外访问正确的 xxx 而无需通过函数 foo 的输出访问它?我想这样做的原因是因为在我的实际代码中,我返回了函数 foo 之外的其他内容,并对 xxx 进行了更改,我希望在执行 foo 后看到它。我可以让该函数每次都返回 xxx,但这将使我的代码不必要地庞大。但我不确定我是否会损害代码质量。我不知道。请建议哪种方式最好。
谢谢
xxx = []
print foo(xxx)
print xxx
在此代码中,您将使用在函数外部创建的列表(称为
foo()
)调用 xxx
。但在函数内,您将递归调用不带参数的 foo()
,因此它会通过默认参数值的表达式修改在函数定义时创建的列表。 (重要的是,每次调用该函数时,这都是相同的列表,而不为该参数提供值。)
比较一下当您像这样定义
foo
时会发生什么:
def foo(xxx = None):
if xxx is None:
xxx = []
if len(xxx) == 5:
return xxx
xxx += [1]
foo()
return xxx
...当你这样定义它时会发生什么:
def foo(xxx = None):
if xxx is None:
xxx = []
if len(xxx) == 5:
return xxx
xxx += [1]
foo(xxx)
return xxx
您可以使用模块memory_graph:
https://pypi.org/project/memory-graph/
轻松查看正在发生的事情:
import memory_graph
def foo(xxx = []):
memory_graph.show( memory_graph.get_call_stack(), block=True) # show graph
if len(xxx) == 5:
return xxx
xxx += [1]
foo()
memory_graph.show( memory_graph.get_call_stack(), block=True) # show graph
return xxx
xxx = []
print(foo(xxx))
print(xxx)
对
foo()
的第一次调用是在“”堆栈帧中使用全局
xxx
foo()
,以便本地“xxx”的默认值(空列表)变量在后面的堆栈帧中使用:
是的,在 Python 中可变类型的默认值发生变化可能有点令人惊讶。
完全披露:我是memory_graph的开发者。