【问题标题】:Why are default arguments in constructor ignored? [duplicate]为什么构造函数中的默认参数被忽略? [复制]
【发布时间】:2020-04-11 00:24:34
【问题描述】:

在 Python 3.7.5 版上测试

考虑一个小的运行示例

from collections import deque


class Tree:
    def __init__(self, ident=None, childs=[]):
        self.ident = ident
        self.childs = childs
        print(f'childs of {ident}: {childs}')

    def traverse_bfs_path(self):
        queue = deque([([], self)])
        while len(queue) > 0:
            path, node = queue.popleft()
            yield path, node
            queue += [(path+[i], n) for i, n in enumerate(node.childs)]


if __name__ == '__main__':
    tree = Tree('a')   # Works as expected
    depth = 1
    spread = 1

    for path, node in tree.traverse_bfs_path():
        if len(path) < depth:
            nc = len(node.childs)
            for _ in range(nc, spread):
                node.childs.append(Tree('-', [])) # without the second argument this will not run!

这会打印到控制台:

a 的子代:[]
- 的孩子:[]
- 的孩子:[]

我想知道 - 当您删除最后一行 [] 中的第二个参数时,Python 不是默认值([] 也是如此),但似乎对 childs 使用相同的数组作为树的前一个实例。

删除第二个参数会导致无限循环并将​​以下内容打印到控制台:

a 的子代:[]
- 的孩子:[]
- 的子级:[ma​​in.Tree 对象位于 0x7efbfe329590>]

有人可以解释这种行为吗?

【问题讨论】:

  • 可变的默认参数是一个常见的问题 - 请参阅docs.python-guide.org/writing/gotchas/…
  • 阅读骗局。使用def __init__(self, ident=None, childs=None): if not childs: childs = [] 作为解决方法

标签: python default-value


【解决方案1】:

您有一个列表作为childs 的默认值,因此您遇到了可变默认参数的副作用。

本质上,Python 在函数/方法第一次运行时评估参数,并将其用于后续运行

https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多