我使用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
这确实有效(注意唯一的区别是块现在是一个列表块):
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
我的问题基本上是为什么看起来chunk / chunk变量的范围似乎取决于它是一个普通变量还是一个列表?
解决方法:
在python中,如果读取变量,可以从周围的范围“拉出”变量.所以以下内容将起作用:
def foo():
spam = 'eggs'
def bar():
print spam
foo()
因为在周围的范围内查找变量’spam’,foo函数.
但是,您无法更改周围范围的值.您可以更改全局变量(如果在函数中将它们声明为全局变量),但是您无法在上述函数中对变量垃圾邮件执行此操作.
(Python 3改变了这一点,它添加了一个新的关键字nonlocal.如果你将垃圾邮件定义为bar内的非本地垃圾,你可以在bar中为该变量分配一个新值.)
现在到你的清单.那里发生的是你根本没有改变变量块.在整个代码中,块指向一个列表,并且仅指向该列表.就python而言,变量块在processchunk函数中不会被改变.
发生的是您更改列表的内容.你可以自由地为chunk [0]分配一个新值,因为那不是变量块,它是由块,第一个索引引用的列表. Python允许这样做,因为它不是变量赋值,而是列表操作.
所以,你的“解决方法”是正确的,如果有点模糊.如果你使用Python 3,你可以在processchunk中将块声明为非本地,然后事情也可以在没有列表的情况下工作.
标签:python,generator,yield,scope,regex
来源: https://codeday.me/bug/20190529/1181908.html