python yield生成器变量范围

aaa*_*210 4 python regex scope yield generator

我使用yield来创建一个生成器,该生成器返回使用正则表达式和re.sub()提取的字符串块.虽然我发现了一种有效的方法,但我对它为什么单向工作而不是另一种工作有点困惑,如下所示:

这不起作用(processchunk()没有分配给splitmsg中声明的块):

def splitmsg(msg):
    chunk = None
    def processchunk(match):
        chunk = match.group(1)
        return ""
    while True:
        chunk = None
        msg = re.sub(reCHUNK,processchunk,msg,1)
        if chunk:
            yield chunk
        else:
            break     
Run Code Online (Sandbox Code Playgroud)

这确实有效(注意唯一的区别是块现在是一个列表块):

def splitmsg(msg):
    chunks = [ None, ]
    def processchunk(match):
        chunks[0] = match.group(1)
        return ""
    while True:
        chunks[0] = None
        msg = re.sub(reCHUNK,processchunk,msg,1)
        if chunks[0]:
            yield chunks[0]
        else:
            break
Run Code Online (Sandbox Code Playgroud)

我的问题基本上是为什么看起来chunk/chunk变量的范围似乎取决于它是一个普通变量还是一个列表?

Mar*_*ers 5

在python中,如果读取变量,可以从周围的范围"拉出"变量.所以以下内容将起作用:

def foo():
    spam = 'eggs'
    def bar():
        print spam
foo()
Run Code Online (Sandbox Code Playgroud)

因为变量'垃圾邮件'正在周围范围内查找,foo功能.

但是,您无法更改周围范围的值.您可以更改全局变量(如果global在函数中声明它们),但是您不能spam对上述函数中的变量执行此操作.

(Python 3对此进行更改,它会添加一个新关键字nonlocal.如果您定义spamnonlocal内部,则bar可以为该变量分配一个新值bar.)

现在到你的清单.那里发生的是你根本没有改变变量chunks.在整个代码中,chunks指向一个列表,并且仅指向该列表.就python而言,chunks变量在processchunk函数内不会改变.

什么不会发生的事情是,你改变的内容列表.您可以自由地为其分配一个新值chunks[0],因为它不是变量chunks,而是chunks第一个索引所引用的列表.Python允许这样做,因为它不是变量赋值,而是列表操作.

所以,你的"解决方法"是正确的,如果有点模糊.如果你使用Python 3,你可以声明chunksnonlocal内部processchunk,然后事情也可以在没有列表的情况下工作.