1

https://github.com/python/cpython/blob/3.6/Lib/linecache.py中有 3 个这样的实例

getines

def getlines(filename, module_globals=None):
    if filename in cache:
        entry = cache[filename]
        if len(entry) != 1:
            return cache[filename][2]

updatecache

def updatecache(filename, module_globals=None):
    if filename in cache:
        if len(cache[filename]) != 1:
            del cache[filename]

lazycache

def lazycache(filename, module_globals):
    if filename in cache:
        if len(cache[filename]) == 1:
            return True
        else:
            return False

我正在编写自己的 linecache 版本并为其编写测试我需要了解元组长度为 1 的场景

有一种情况是 in 中的语句getlines被执行。这是第一次访问文件并将其存储在缓存中,然后在第二次访问之前将其删除。但我仍然无法弄清楚为什么它存在于其他两个函数中。

如果有人可以帮助我了解使用此长度检查的目的,那将非常有帮助。

4

1 回答 1

2

查看代码在缓存中存储值的位置。它可以在 下存储两种不同的值cache[filename]

  • 大小、修改时间、行列表和名称(此处此处)的 4 元组。
  • 根据需求返回行列表的函数的 1 元组(此处)。

1-tuple 用于设置模块的延迟加载。普通文件,要延迟加载它们,你只需openread. 但是模块源可以从模块的加载器中获得(通过导入系统找到),但不能通过打开和读取文件来获得——例如,zipimport模块。所以lazycache必须隐藏加载器的get_source方法,所以如果它以后需要这些行,它可以得到它们。

这意味着,每当它使用这些缓存值时,它必须检查它存储的是哪种类型并做不同的事情。如果它现在需要这些行,并且它有一个惰性 1 元组,它必须去加载这些行(通过updatecache; 如果它正在检查缓存驱逐并且它找到一个从未评估过的惰性元组,它会丢弃它;等等。

还要注意 in updatecache,如果它是从惰性 1 元组加载文件,它没有 mod time,这意味着 in checkcache,它无法检查文件是否过时。但这对于模块源来说很好——即使您更改了文件,旧版本仍然是已import编辑和正在使用的版本。


如果您是从头开始设计它,而不是破解自 1.x 早期黑暗时代以来就存在于 stdlib 中的东西,您可能会以非常不同的方式设计它。例如,您可能使用一个类,或者可能使用两个实现相同接口的类。

另外,请注意,其中的大量代码linecache用于处理与加载模块源相关的特殊情况,除非您尝试构建反映 Python 代码的东西(就像这样traceback做),否则您不需要任何. (即使你这样做了,你也可能想要使用inspect模块而不是直接与导入系统对话。)

因此,linecache可能不是基于您自己的行缓存的最佳示例代码。

于 2018-06-27T08:40:43.523 回答