[ Python ]请教一个闭包传参的问题

2020-03-23 20:44:22 +08:00
 shaodamao

各位大佬,下面的代码,嵌套函数定义def w():时,如果不传参,输入就符合预期,如果传了上层参数def w(*l):,结果就会报错。 请问传参不传参,影响在哪里呢?

def f(*l):
    yield from l

def closure(*l):
    a=f(*l)
    def w(): # 这里是 def w(*l)下面就会报错,报错内容最下方
        nonlocal a
        try:
            return next(a)
        except Exception:
            a=f(*l)
            return next(a)
    return w

c=closure(1,2)
for i in range(5):
    print(c())

输出为:

1
2
1
2
1

报错为:

1
2
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-2-5b268514707e> in w(*l)
      8         try:
----> 9             return next(a)
     10         except Exception:

StopIteration:

During handling of the above exception, another exception occurred:

StopIteration                             Traceback (most recent call last)
<ipython-input-2-5b268514707e> in <module>
     15 c=closure(1,2)
     16 for i in range(5):
---> 17     print(c())
     18

<ipython-input-2-5b268514707e> in w(*l)
     10         except Exception:
     11             a=f(*l)
---> 12             return next(a)
     13     return w
     14

StopIteration:
1002 次点击
所在节点    问与答
2 条回复
imn1
2020-03-23 21:43:39 +08:00
def w(*L):
……
except Exception:
a=f(*L)
……
return w(*l)

这样能理解了吧?
l 作用域在整个 closure 内,不传 w 内也是直接用它
L 作用域只在 w 内,传的时候才用到用它,不传的话遇到 Exception 就没有值了
whoami9894
2020-03-23 22:47:54 +08:00
不定义参数 w 里拿到的 l 是 def closure 的参数`(1, 2)`,定义了`w(*l)` w 里拿到的 l 是`(,)`

正常情况下你把 generator 封装在 closure 里,一直调用 next 直到抛出 StopIteration,然后重置 generator 为 closure 里的 l 也就是`(1, 2)`,接着继续 next ;出错的情况里抛出 StopIteration 后初始化了一个空 generator (`a = f()`),调用 next 后立即抛出 StopIteration,这个 except 语句里的异常你没处理所以程序直接挂了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/655497

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX