代码之家  ›  专栏  ›  技术社区  ›  showkey

为什么不能重置字典?[副本]

  •  0
  • showkey  · 技术社区  · 4 年前

    我写了一个函数递归地列出所有文件和目录。

    import os
    def walk_dir(path,dir_list=[],file_list=[]):
        for fname in os.listdir(path):
            fullname = os.path.join(path, fname)
            if  os.path.isdir(fullname) :
                dir_list.append(fullname)
                walk_dir(fullname,dir_list,file_list)
            elif os.path.isfile(fullname) :
                file_list.append(fullname)
        return {'dir':dir_list,'file':file_list}
    


    我创建一个目标目录来测试我的代码。

     mkdir -p /tmp/test
     cd /tmp/test
     mkdir -p  test{1..3}
     cd  test1
     touch /test1/test1{1..3}
     cd ../test2
     touch /test2/test2{1..2}
    

    这是我要尝试的目标目录:

    tree  /tmp/test
    /tmp/test
    ├── test1
    │   ├── test11
    │   ├── test12
    │   └── test13
    ├── test2
    │   ├── test21
    │   └── test22
    ├── test3
    

    把所有的文件都放进去 /tmp/test .

    x = walk_dir('/tmp/test')
    x['dir']
    ['/tmp/test/test1', '/tmp/test/test3', '/tmp/test/test2']
    

    {} --字典里没有。

    x = {}
    x
    {}
    x['dir']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'dir'
    dir_list
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'dir_list' is not defined
    

    也许每个变量都被初始化为none。

    x = walk_dir('/tmp/test')
    x['dir']
    ['/tmp/test/test1', '/tmp/test/test3', '/tmp/test/test2', '/tmp/test/test1', '/tmp/test/test3', '/tmp/test/test2']
    

    我已重置 x 作为 {} ,为什么x['dir']包含6个目录而不是3个目录?

    1 回复  |  直到 4 年前
        1
  •  1
  •   ProfOak    4 年前

    这是蟒蛇的陷阱之一。

    空列表的默认参数是在函数定义中创建的。它在函数调用之间仍然存在。

    >>> def test_func(param=[]):
    ...     param.append(1)
    ...     print(param)
    ... 
    >>> test_func()
    [1]
    >>> test_func()
    [1, 1]
    >>> test_func()
    [1, 1, 1]
    >>> test_func()
    [1, 1, 1, 1]
    >>> test_func()
    [1, 1, 1, 1, 1]
    >>> test_func()
    [1, 1, 1, 1, 1, 1]
    

    如果你看你的输出,你会看到重复的。每条路径存在两次。如果你再运行一次,它应该有三个重复每个,以此类推。这只适用于可变类型。所以像列表和字典之类的东西会表现出这种行为。如果不打算使用此行为,请避免将其用作默认参数。

    而是使用将默认参数设置为None并在函数体中选中它。

    >>> def test_func2(param=None):
    ...     if param is None:
    ...         param = []
    ...     param.append(1)
    ...     print(param)
    ... 
    >>> test_func2()
    [1]
    >>> test_func2()
    [1]
    >>> test_func2()
    [1]