python 文字是否保存在函数体内?

the*_*dox -1 python scopes

我有一个函数需要在一个相当紧密的循环中执行,所以它对性能很敏感。它的过滤功能旨在节省更昂贵的工作。大多数功能只是对静态列表的检查。

所以(去掉一些不相关的细节)我可以在这里做两件不同的事情:

 def my_filter(arg):
    SAFE_VALS = {
        'a',
        'b',
        'f',
        'i',
        'm'
    }
   # the real list is much larger, but 
   # it is a static set like the above...

    return arg in SAFE_VALS
Run Code Online (Sandbox Code Playgroud)

或者

 # make this a module level constant
 SAFE_VALS = {
        'a',
        'b',
        'f',
        'i',
        'm'
    }

 def my_filter(arg):
    return arg in SAFE_VALS
Run Code Online (Sandbox Code Playgroud)

我知道 Python 将不得不查看更高的范围级别才能找到模块级别的版本——但我不知道的是,my_filter每次运行函数时,编译版本是否有效地重新创建了这个集合,或者文字是否“烘焙” in" 到函数 def. 如果每次调用都分配一个新集合,那么我感觉使用模块级版本会更好——如果不是,我不会通过将文字提升到函数范围之外而获得任何好处。

现在分析数据足够嘈杂,我没有看到明显的区别。但是,如果该集合包含更多的长字符串,我会吗?或者,这些形式之间是否存在显着差异?

use*_*ica 5

作为语言语义的问题,{'a', 'b', 'f', 'i', 'm'}意思是“用这些内容制作一个新的集合”。语言语义允许将现有对象重用于不可变类型,但集合是可变的。

作为一个实现细节,CPython 目前优化了形式的表达式x in {stuff},其中右侧是一个只包含常量的集合表达式。在这种情况下,Python 将预先计算一个frozenset 并将其保存在代码对象的co_consts. 将集合保存到变量会阻止优化。

为了保证集合不被重新计算,独立于实现细节,您应该自己预先计算集合并保存SAFE_VALS为全局变量。