RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1599566
Accepted
Radiance
Radiance
Asked:2024-11-12 19:53:37 +0000 UTC2024-11-12 19:53:37 +0000 UTC 2024-11-12 19:53:37 +0000 UTC

循环中的迭代器与列表迭代器不同

  • 772

在尝试reduce()从模块实现方法时functools,我遇到了对迭代器工作原理的误解。使用该方法时iter(),我们接收列表的迭代器seq并将其分配给一个变量seqIter,然后该方法next()将列表的第一个元素传递给该变量value。

然而,当执行循环时,我们使用可迭代对象的for迭代器,而可迭代对象又是列表的迭代器。问题是,在循环的每一圈上它等于什么?xseqIterx

在这段代码中,我们看到了reduce在列表中添加数字的方法的实现:

def reduce(func, seq):
    seqIter = iter(seq)
    value = next(seqIter)
    for x in seqIter:
        value = func(value, x)
    return value

list = [1,2,3]
print("Sum seq is:", reduce(lambda x,y: x+y, list))

结果:

python .\reduceImplemention.py
Sum seq is: 6

在尝试缩短代码时,出现以下结果:

def reduce(func, seq):
    value = next(iter(seq))
    for x in iter(seq):
        value = func(value, x)
    return value

list = [1,2,3]
print("Sum seq is:", reduce(lambda x,y: x+y, list))

根据字符串的解释以括号开头(如数学中一样)的规则,应该先执行表达式iter(seq),然后执行字符串的其余部分。我们还使用 方法将列表迭代器传递iter()到循环中。然而,结果变成:forseq

python .\reduceImplemention.py
Sum seq is: 7

问题可能出在循环中for,因此我们创建一个变量seqIter并为其赋值iter(seq),并在循环中将其更改为for x in seqIter。结果还是一样:

python .\reduceImplemention.py
Sum seq is: 7

因此,问题是:为什么该方法next没有在方法代码块的最开始处应用reduce?还是循环条件?

python
  • 2 2 个回答
  • 69 Views

2 个回答

  • Voted
  1. Best Answer
    Алексей Сундеев
    2024-11-12T20:39:30Z2024-11-12T20:39:30Z

    您使用迭代器两次iter(seq)而不保存迭代器状态。当您编写 时for x in iter(seq),您实际上是在循环中的每个点为序列创建一个新的迭代器seq,这会导致循环的第一步遗漏您next(seqIter)在代码的第一个版本中已经选取的元素。因此,在循环的第一步中,您从列表的第一个元素开始,然后在循环中跳过它并从第二个元素开始。

    要解决此问题,您需要在两种情况下使用相同的迭代器。按类型:

    def reduce(func, seq):
        seqIter = iter(seq)
        value = next(seqIter)
        for x in seqIter:
            value = func(value, x)
        return value
    
    list = [1, 2, 3]
    print("Sum seq is:", reduce(lambda x, y: x + y, list))  # Результат: 6
    

    这里seqIter它被创建一次,并且在循环执行期间保留其状态

    • 2
  2. Vladimir Bogdanov
    2024-11-12T20:48:12Z2024-11-12T20:48:12Z

    作为纯粹的学术兴趣,我想知道是否有可能在没有迭代器的情况下实现类似的reduce。毫无疑问,迭代器解决方案很棒。

    我决定在发电机上实现它。

    reduce1 选项很紧凑,但有一个缺点:“*_”存储先前计算的 func 值的元组。请记住 28+ 字节,该解决方案适用于小型列表。尽管在某些情况下这种副作用肯定是有用的。

    reduce2 选项消除了第一个选项的缺点,但它需要一个空闲的 for 循环来运行生成器。

    reduce3 选项需要连接集合模块并创建一个双端队列类。您可以创建自己的小类,但这会使代码变得混乱。这个选项介于前面的选项之间。 deque 类的“额外”实例是从内存中创建的,但 deque 会自动消耗生成器。双端队列只存储一个值——调用 func 的最后一个结果。

    PS如果有人知道获取生成器最后一个元素的更“体面”的选项,我将不胜感激。

    from collections import deque
    
    def reduce1(func, seq):
        value = None
        try:
            *_, result = (value := x if value is None else func(value, x) for x in seq)
        except Exception as exc:
            raise TypeError("reduce() of empty iterable with no initial value") from exc
        return result
    
    def reduce2(func, seq):
        value = None
        g = (value := x if value is None else func(value, x) for x in seq)
        for _ in g: pass
        if value:
            return value
        else:
            raise TypeError("reduce() of empty iterable with no initial value") from None
    
    def reduce3(func, seq):
        value = None
        g = (value := x if value is None else func(value, x) for x in seq)
        result = deque(g,1)
        try:
            return result.pop()
        except Exception as exc:
            raise TypeError("reduce() of empty iterable with no initial value") from exc
    

    旧版本有一些评论中指出的缺点:

    def reduce(func, seq):
        value = 0
        for x in iter(seq):
            value = func(value, x)
        return value
    
    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5