【问题标题】:iterator function does not iterate over all elements迭代器函数不会迭代所有元素
【发布时间】:2023-02-22 21:42:23
【问题描述】:

我有两个功能:

# function to get number of wanted atom
def atom_number_grabber(sum_formula, wanted_atom):
    match = re.match(r"([A-Z][a-z]*)([0-9]*)", sum_formula, re.I)
    if match:
        items = match.groups()
    if items[0] == wanted_atom:
        atom_number = items[1]
        if not atom_number:
            atom_number = "1"
        return atom_number
    else:
        pass

#function to iterate over all elements
def iterator(sum_formula_list, atom_number_grabber, wanted_atom):
    for sum_formula in sum_formula_list:
        return atom_number_grabber(sum_formula, wanted_atom)

但是,当我使用迭代器函数时,它不会遍历列表中的所有元素

test_list = ["C25", "H32", "O8"]

iterator(sum_formula_list = test_list, atom_number_grabber = atom_number_grabber, wanted_atom = "O")

输出:

期望的输出:

8

令我惊讶的是,该函数仅遍历第一个元素;因此,如果我将 wanted_atom 更改为“C”,代码将正常工作:

iterator(sum_formula_list = test_list, atom_number_grabber = atom_number_grabber, wanted_atom = "C")

输出

25

【问题讨论】:

  • for 循环中的无条件 return 将在第一次迭代时结束该循环。
  • 谢谢,你是对的!

标签: python loops for-loop jupyter


【解决方案1】:

还不能发表评论,所以我会把它作为答案发布,我会随着它的进行进行编辑。

首先,你不应该将你的函数作为参数传递给 iterator(),如果它被定义,你可以在任何其他函数的任何地方使用它。

其次,你为什么使用原始字符串?如果我没记错的话,它仅用于将反斜杠视为普通字符而不是转义字符。

return 语句使其在 for 循环中提前结束。这就是为什么它适用于 C 而不是 O。

【讨论】:

    【解决方案2】:

    当你在 for 循环中有一个无条件的 return 时,该循环只会迭代一次,然后退出。

    假设你的函数被称为iterator,也许你想返回...一个迭代器。在这种情况下,您可以使用 yield 而不是 return。让它有条件,这样你只有在有结果的时候才会屈服。像这样:

    def iterator(sum_formula_list, atom_number_grabber, wanted_atom):
        for sum_formula in sum_formula_list:
            result = atom_number_grabber(sum_formula, wanted_atom)
            if result:
                yield result
    

    现在主程序可以使用该迭代器,例如使用*

    print(*iterator(sum_formula_list = test_list, atom_number_grabber = atom_number_grabber, wanted_atom = "O"))
    

    输出:8

    其他cmets

    • 您的第一个函数中有一个缩进错误:第二个if 可能会在未定义items 时执行。第二个if块应该在第一个if块的块内。

    • else: pass没用。

    • 当您使用 re.I 标志时,将大小写与 [A-Z][a-z]* 混合使用是没有用的。那就做[A-Z]+吧。

    • 您可以通过在 match 对象上建立索引来访问组。无需检索 groups。请注意,match[0] 是整场比赛,match[1] 是第一组。

    • if not atom_number 可以使用逻辑 or 运算符来完成,例如 return match[2] or "1"

    • 无需将 atom_number_grabber 作为参数传递——它可以直接使用。

    • 有第一个功能好像比较实用仅有的负责提取部分,而第二个函数将对所需的原子进行过滤。

    • 第二个函数可以使用理解语法。

    这是如何完成的:

    import re 
    
    # function to split string into atom name and number
    def atom_parts(sum_formula):
        match = re.match(r"([A-Z]*)([0-9]*)", sum_formula, re.I)
        return match[1], int("0" + match[2]) or 1
    
    # function to iterate over all elements
    def iterator(sum_formula_list, wanted_atom):
        return (number for name, number in map(atom_parts, sum_formula_list) 
                       if name == wanted_atom)
    
    test_list = ["C25", "H32", "O8"]
    
    print(*iterator(sum_formula_list = test_list, wanted_atom = "O"))  # 8
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      相关资源
      最近更新 更多