【问题标题】:getting iterator from if any()从 if any() 获取迭代器
【发布时间】:2019-04-29 15:43:17
【问题描述】:

我有这个简单的功能:

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”的值,这样我就可以使用 .find() 函数返回它的索引。上面的代码不起作用,因为它告诉我:

NameError:未定义全局名称“x”

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

for x in my_list:
    print x

【问题讨论】:

  • 你想要next()而不是any()
  • 你能再解释一下吗。添加 next() 将如何帮助我返回 x 的值? Any 在这里是正确的功能,它按预期工作,我只需要访问要在 .find() 中使用的 x 的值
  • x = next((x for x in prefixes if x in filename), None):if x:(或者可能是 filename.startswith(x)-- 假设您想要第一个,请对所有数学使用列表组合
  • @Chris_Rands 这个工作除了最后一次迭代,然后它抛出一个错误Traceback (most recent call last): File "main.py", line 78, in <module> better_func(keys) File "main.py", line 26, in better_func if filename.startswith(x): TypeError: startswith first arg must be str, unicode, or tuple, not NoneType
  • 我可以将“None”的值更改为默认值,但这似乎不是很pythonic,以满足最后一次迭代。那问题对吗?

标签: python iterator any


【解决方案1】:

而不是

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()))

【讨论】:

  • x 只是这里的第一个前缀,不是想要的
  • 我试过了,但它没有按预期工作。它为所有键返回 false
  • @William 我的错,我解决了这个问题
  • 你不需要iter;只是next((...), None)
  • 你是我最终实现的第三个代码块。我最初每次都使用“try:except:”块从下一个函数中捕获 StopIteration,但是您使用默认值(设置为 None)并将其放在 if 语句中的解决方案更优雅
【解决方案2】:

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

【讨论】:

  • 可能值得注意的是,从技术上讲,这不会将与条件匹配的xfirst 值分配给found,而是将all 值直到并包括第一个值,有点像“泄漏”列表理解。此外,如果 none 元素满足条件,found 将采用 xlast 值。
  • 我把x in filename放错地方了;我认为它现在已修复。不过,我不确定是否将found 设置为以前的值是否重要,因为在any 本身返回之前,您无法访问它的值(即在any 之外)。
猜你喜欢
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 2011-09-28
  • 1970-01-01
  • 2020-01-15
  • 2018-03-06
相关资源
最近更新 更多