草庐IT

python - 迭代器作为 bool 语句?

coder 2023-08-26 原文

我遇到了这段代码:

def myzip(*args):
    iters = map(iter, args)
    while iters:
        res = [next(i) for i in iters]
        yield tuple(res)

我不确定:

  • 为什么列表理解不需要捕获 StopIteration
  • while iters 如何像我尝试的那样工作:

    x=[1,2]
    x=iter(x)
    if x: 
        print("Still True")
    next(x)
    next(x)
    if x: 
        print("Still True")
    

并且在这两种情况下它仍然打印 "Still True"

代码的作者还说,因为 map 在 3.X 中返回一个“一次性迭代器”,并且“只要我们在循环中运行一次列表理解,iters 就会耗尽但仍然是 True( 并且res 将永远是 [])”。如果我们使用 3.X,他建议使用 list(map(iters, args)

我不确定这个改变实际上是如何帮助它工作的,因为我认为即使迭代器在 StopIteration 点它仍然是 True(基于什么我之前试过)。

编辑:

作者以此为例

>>> list(myzip('abc', 'lmnop'))
[('a', 'l'), ('b', 'm'), ('c', 'n')]

最佳答案

这个问题有几个方面。

python-2.x

map 返回一个 listwhile iters 只是确保代码不会进入循环,以防万一没有 *args 传递给函数。这是因为空列表被认为是 False 而非空列表被认为是 True

如果没有*args,它不会进入循环并隐式返回,然后引发StopIteration

如果至少有一个参数,则 while iters 等同于 while True 并且它依赖于其中一个迭代器来引发 StopIteration 耗尽后。不需要捕获 StopIteration(至少在 Python 3.7 之前),因为您希望 myzip 在一个可迭代对象耗尽时停止

python-3.x

在 Python 3 中 map 返回一个 map 实例,它总是被认为是 True 所以 while 循环是等价的为 while True

但是,在python-3.x 中有一个问题:在遍历一个map 实例后,它会被耗尽。在第一次迭代(while 循环)中按预期工作,但在下一次迭代中 map 将为空,它只会创建一个空列表:

>>> it = map(iter, ([1,2,3], [3,4,5]))
>>> [next(sub) for sub in it]
[1, 3]
>>> [next(sub) for sub in it]
[]

没有任何东西可以引发 StopIteration,因此它将进入无限循环并永远返回空的 tuple。如果 iters 列表为空,这也是您不想进入 while 循环的原因!

可以通过以下方式修复(如所述):

iters = list(map(iter, args))

一般观察

只是说明它如何更有意义:

def myzip(*args):
    if not args:
        return
    iters = [iter(arg) for arg in args]  # or list(map(iter, args))
    while True:
        res = [next(i) for i in iters]
        yield tuple(res)

如果您希望代码符合 python-3.7(感谢@Kevin 指出这一点),您明确需要捕获 StopIteration。有关更多信息,请参阅 PEP-479 :

def myzip(*args):
    if not args:
        return
    iters = [iter(arg) for arg in args]  # or list(map(iter, args))
    while True:
        try:
            res = [next(i) for i in iters]
        except StopIteration:  
            # the StopIteration raised by next has to be catched in python-3.7+
            return
        yield tuple(res)

后面的代码也适用于 python-2.7 和 python-3.x < 3.7,但它只需要在="" python="" 3.7+="" 中捕获="">StopIteration

关于python - 迭代器作为 bool 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45772331/

有关python - 迭代器作为 bool 语句?的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  5. ruby - 如何在 Ruby 中向现有方法定义添加语句 - 2

    我注意到类定义,如果我打开classMyClass,并在不覆盖的情况下添加一些东西我仍然得到了之前定义的原始方法。添加的新语句扩充了现有语句。但是对于方法定义,我仍然想要与类定义相同的行为,但是当我打开defmy_method时似乎,def中的现有语句和end被覆盖了,我需要重写一遍。那么有什么方法可以使方法定义的行为与定义相同,类似于super,但不一定是子类? 最佳答案 我想您正在寻找alias_method:classAalias_method:old_func,:funcdeffuncold_func#similartoca

  6. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

随机推荐