从 if any() 获取迭代器

getting iterator from if any()

我有这个简单的功能:

keys = ['snmt1/metadata/table1/ref_table1_20190324124365.csv', 'snmt1/metadata/table2/table2_ref_20190324124365.csv', 'snmt1/metadata/table3/table3_20190324124365.csv']


def better_func(keys):
  for item in keys:
    split_key = item.split("/")
    filename = str(split_key[-1])
    prefixes = ['strm','ref','trunc']
    if any(x in filename for x in prefixes):
      location = filename.find(x)
      if location == 0:
        print True
      else:
        print "another false"
    else:
      print False

我需要的是 "x" 的值,这样我就可以 return 使用 .find() 函数对其进行索引。上面的代码不起作用,因为它告诉我:

NameError: global name 'x' is not defined

我明白了,但是我如何才能像通常在 for 循环中那样访问 "x"?

for x in my_list:
    print x

而不是

if any(x in filename for x in prefixes):
    # do stuff with x

你可以做到:

x = next((p for p in prefixes if p in filename), None)
if x:
    # do stuff with x

这将创建一个生成器,并从中获取下一个值 - 即第一个值。 None 的第二个参数是标记值:如果迭代器引发 StopIteration,而不是传递此异常,则返回 None,并绑定到 x

这在这里看起来不太有用,但是当你想要满足条件的序列的第一个元素时,它确实派上用场,如果没有这样的元素,则进行回退操作:

elt = next((x for x in range(10) if x > 5), None)
if elt is not None:
    print("{} satisfies the condition".format(elt))
else:
    print("No such element found")

请注意,生成器也是迭代器,因此您可以直接对它们调用 next。对于列表、字典或其他任何可迭代对象,您需要先调用 iter。例如,这对于从字典中获取任意值很有用:

value = next(iter(d.values()))

Python 3.8(将于 2019 年底发布)将提供赋值表达式,部分是为了解决为 any 的成功命名见证人的确切用例。

import os


def better_func(keys):
    prefixes = ['strm', 'ref', 'trunk']
    for item in keys:
        filename = os.path.basename(item)
        if any((found := x) for x in prefix if x in filename):
           if filename.startswith(found):
               print True
           else:
               print "another false"
        else:
           print False