nested list comprehension with os.walk

2019-03-20 12:05发布

Trying to enumerate all files in a certain directory (like 'find .' in Linux, or 'dir /s /b' in Windows).

I came up with the following nested list comprehension:

from os import walk
from os.path import join
root = r'c:\windows'      #choose any folder here
allfiles = [join(root,f) for f in files for root,dirs,files in walk(root)]

Unfortunately, for the last expression, I'm getting:

NameError: name 'files' is not defined

Related to this question, which (although working) I can't understand the syntax of the nested list comprehension.

2条回答
孤傲高冷的网名
2楼-- · 2019-03-20 12:19

You need to reverse the nesting;

allfiles = [join(root,f) for root,dirs,files in walk(root) for f in files]

See the list comprehension documentation:

When a list comprehension is supplied, it consists of a single expression followed by at least one for clause and zero or more for or if clauses. In this case, the elements of the new list are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce a list element each time the innermost block is reached.

In other words, since you basically want the moral equivalent of:

allfiles = []
for root, dirs, files in walk(root):
    for f in files:
        allfiles.append(f)

your list comprehension should follow the same ordering.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-03-20 12:27

it is:

allfiles = [join(root, f) for _, dirs, files in walk(root) for f in files]
查看更多
登录 后发表回答