Python 列表作用域位于函数之外

问题描述 投票:0回答:2

我遇到了一个很难解释的问题,因为涉及很多代码。所以归结为以下问题。

我正在尝试访问函数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,但这将使我的代码不必要地庞大。但我不确定我是否会损害代码质量。我不知道。请建议哪种方式最好。

谢谢

python list function
2个回答
3
投票
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

0
投票

您可以使用模块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的开发者。

© www.soinside.com 2019 - 2024. All rights reserved.