【问题标题】:Are python literals saved inside function bodies?python 文字是否保存在函数体内?
【发布时间】:2021-03-18 10:41:34
【问题描述】:

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

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

 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

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

 def my_filter(arg):
    return arg in SAFE_VALS

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

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

【问题讨论】:

    标签: python scopes


    【解决方案1】:

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

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

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

    【讨论】:

    • 啊——谢谢你提到co_consts——我应该意识到我可以在那里看到它。
    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 2021-12-16
    • 2018-03-30
    相关资源
    最近更新 更多