摄影:产品经理烤牛油串竟然有点好吃
在文章《生成器运行时机导致的难以察觉的 bug》一文中,我最后解释为什么没有过滤掉无效数据
的原因有问题。当时使用的是如下一段代码:
outer = 123 def i_am_generator(): print('生成器函数运行了。外部变量的值为:', outer) yield generator = i_am_generator()print(f'现在返回的是一个生成器对象:{generator}') outer = 456for _ in generator: ...
但这段代码中,生成器i_am_generator
使用的始终是外部的变量。
但在实际举的例子中:
def do_filter(datas, to_filter): for data in datas: if to_filter in data: continue yield data
这个生成器是会接收传入参数的。它会使用参数传进来的值,而不是外部变量。在这种情况下,通过“值传递”进来的参数实际上是会有效的。我们修改一下原来的i_am_generator
生成器:
outer = 123 def i_am_generator(data): print('生成器函数运行了。外部变量的值为:', data) yield generator = i_am_generator(outer)print(f'现在返回的是一个生成器对象:{generator}') outer = 456for _ in generator: ...
运行效果如下图所示:
可以看到,在这种情况下,生成器里面打印出来的是outer
变量修改之前的值,而不是修改后的值。outer
变量一开始的值123
通过值传递
的方式传入生成器函数以后,就生效了。相当于复制了一份,所以原来的数据怎么修改都不会影响这个复制出来的数据。所以当我们后面修改outer
的时候,并不会影响生成器中早已传入的值。
同理,对于我们举的过滤数据的例子,真正导致无法过滤无效数据
的原因在这里:
def trash_filter(): datas = ['有效信息', '重要信息', '隐私信息', '脏数据', '保密信息', '无效数据', '大数据'] for word in ['无效', '脏']: result = do_filter(datas, word) return result
在这个循环里面,有两个生成器,但是他们都赋值到了result
变量里面。所以第二个生成器就直接覆盖了第一个生成器。第一个生成器根本就没有执行。
所以最后执行的时候,实际上只有do_filter(datas, '脏')
对应的生成器运行了。所以才会只过滤包含脏
的内容。