2016-03-18 40 views
-1

我想缩短这个函数的任何项目的任何部分列表:筛选任何包含从其他列表

def get_filenames(path, banned_files=()): 
    file_list = [] 
    for root, _, files in os.walk(path): 
     BANNED_FILES = banned_files 
     for f in files: 
      for string in BANNED_FILES: 
       if string in f: 
        continue 
      path = os.path.join(root, f) 
      file_list.append(path) 
    return file_list 

这样使用:

filenames = get_filenames(CLIENT_TESTS_PATH, banned_files=['__init__.py', '.pyc', 'accounts.py, otherfile.py']) 

使得从任何文件CLIENT_TESTS_PATH没有任何被禁止的文件。我不能仅仅检查文件路径是否在带有列表理解的禁止文件中,因为我关心是否可以在客户端文件中的任何位置找到禁止的文件。我怎样才能缩短这与一个过滤器,列表理解和或lambda有效?我只想要那个目录下的文件,而不是下面的目录。 谢谢

对于

def get_files(path, banned_files=[]): 
    return [os.path.join(root, fname) for root, _, fnames in os.path.walk(path) for fname in fnames \ 
       if not any(bad_fname in fname for bad_fname in banned_files)] 

我得到

In [2]: CLIENT_TESTS_PATH = "/home/cchilders/work_projects/webapi"  

In [3]: get_files(CLIENT_TESTS_PATH) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-3-3c5a75968d68> in <module>() 
----> 1 get_files(CLIENT_TESTS_PATH) 

/home/cchilders/scripts/my_scripting_library/sysadmin.py in get_files(path, banned_files) 
    15 
    16 def get_files(path, banned_files=[]): 
---> 17  return [os.path.join(root, fname) for root, _, fnames in os.path.walk(path) for fname in fnames \ 
    18     if not any(bad_fname in fname for bad_fname in banned_files)] 
    19 

TypeError: walk() takes exactly 3 arguments (1 given) 
+2

不要使用可变默认参数 - 见http://stackoverflow.com/q/1132941/3001761 – jonrsharpe

+2

在他的代码,这不是一个问题,因为OP不会改变参数,也不会尝试返回它。 – zmo

+2

@zmo - 你说得对。这里没有危险。但它仍然不是一个好习惯。一个元组也可以在默认情况下工作。 – mgilson

回答

1

喜欢的东西:

banned_files=['__init__.py', '.pyc', 'accounts.py', 'otherfile.py'] 
file_list = ["""Some list of files here"""] 
new_list = {file_name for file_name in file_list for bf in banned_files if bf not in file_name} 

这将过滤掉任何东西,都在文件名中这些字符串。这意味着像"my_accounts.py.txt"将被阻止。将它们分开可能会更好。例如:

banned_files=['__init__.py', 'accounts.py', 'otherfile.py'] 
banned_extensions = ['.pyc'] 
new_list = {file_name for file_name in file_list for ext in banned_extensions if file_name not in banned_files and not file_name.endswith(ext)} 

编辑包含os.walk ...一秒钟。

+0

我喜欢高尔夫,但我不明白。有3个大声笑我们可以分解下来 – codyc4321

+0

@ codyc4321是的,这是一个集合的理解。随着限制的增加,理解会变得非常混乱。但是,分别应用禁止的文件和扩展名实际上会更快。 – Goodies

+0

实际上这不是我在想的,但似乎最好 – codyc4321

1

列表理解:

def get_filenames(path, banned_files=()): 
    return [os.path.join(root, f) for root,_,files in os.walk(path) for f in files] 

,做同样的事情,你发布的代码,但它可能是你想要的东西没有做。你的for string in BANNED_FILES:循环完全没用,因为它所做的只是继续,但continue只能在当前循环中使用;它不会影响for f in files:循环,因此除了浪费处理时间之外,内部循环完全不起作用。为了做我认为你,这样做:

def get_filenames(path, banned_files=()): 
    return [os.path.join(root, f) 
      for root,_,files in os.walk(path) 
       for f in files 
        if not any(string in f for string in banned_files) 
    ] 
0

列表理解是恕我直言,最清晰的方式:

[os.path.join(root, f) for root, _, files in os.walk(path) \ 
for f in files if all([bf not in f for bf in banned_files])] 

不要忘记在所有的()括号:

In [7]: [f for f in ['abc','def','ghi','jkl'] if all([bf not in f \ 
for bf in ['a','e','z']])] 
Out[7]: ['ghi', 'jkl'] 

In [8]: [f for f in ['abc','def','ghi','jkl'] if all(bf not in f \ 
for bf in ['a','e','z'])] 
Out[8]: ['abc', 'def', 'ghi', 'jkl'] 
+0

这些似乎让它倒退,没有禁止的文件可以在f .. – codyc4321

+0

它现在的作品。不要忘记'all()'中的'[]'。 –

0

我会做这种方式:

def get_filenames(path, banned_files=[]): 
    banned = '|'.join(banned_files) 
    return [os.path.join(root, f) 
      for root, _, files in os.walk(path) 
      for f in files 
      if f not in banned] 

说明:

|不能在文件名中使用,所以我们可以使用它作为一个包含所有被禁止的文件字符串分隔符。检查发现的文件名对单个字符串要快得多。

+0

这些似乎让它倒退,没有被禁止的文件可以在f .. – codyc4321

1
[os.path.join(root, fname) for root, _, fnames in os.path.walk(path) for fname in fnames \ 
    if not any(bad_fname in fname for bad_fname in banned)] 
+0

是'任何',这是我需要的功能 – codyc4321

1

试试这个:

def get_filenames(path, banned_files=()): 
    file_list = [os.path.join(root, f) for root, _, files in os.walk(path) 
       for f in files if all(s not in f for s in banned_files)] 
    return file_list 
+0

这超出了当前目录 – codyc4321

相关问题