我可以将文件视为python中的列表吗?

时间:2019-04-10 00:37:33

标签: python list file

这是一个问题,但是我也只是希望我不必编写一堆代码即可获得想要的行为。 (此外,如果它已经存在,它的运行速度可能比我写的还要快。)我有很多无法容纳在内存中的大型数字列表-至少不是同时所有。很好,因为一次只需要每个列表的一小部分,而且我知道如何将列表保存到文件中并读出所需的部分列表。问题是我执行此操作的方法效率不高,因为它涉及遍历文件中所需的部分。因此,我想知道是否有某个库或某个我找不到的库使我可以使用我熟悉的[]标记来索引文件,就好像它是一个列表一样。由于我自己编写文件,因此我可以根据需要进行格式化,但是目前我的文件只包含列表元素,其中\n是值之间的分隔符。

只是总结一下我要寻找的内容/使其更具体。

  1. 我想使用列表索引符号(包括切成子列表和否定索引)来访问写在文件中的列表的内容
  2. 被访问的子列表(例如f[1:3])应作为内存中的python列表对象返回
  3. 我希望能够分配给文件的索引(例如f[i] = x应该在对应于索引{{1}的位置将值x写到文件f })

说实话,我不希望这种情况存在,但您永远不知道何时错过您的研究。所以,我想问一下。附带说明一下,如果不存在,是否可以在python中重载i运算符?

2 个答案:

答案 0 :(得分:1)

如果数据是纯数字的,则可以考虑使用numpy数组,并以npy格式存储数据。以这种格式存储后,您可以将内存映射文件加载为:

>>> X = np.load("some-file.npy", mmap_mode="r")
>>> X[1000:1003]
memmap([4, 5, 6])

此访问将直接从磁盘加载,而无需加载前导数据。

答案 1 :(得分:1)

实际上,您可以通过编写一个简单的类来做到这一点:

class FileWrapper:

    def __init__(self, path, **kwargs):
        self._file = open(path, 'r+', **kwargs)

    def _do_single(self, where, s=None):
        if where >= 0:
            self._seek(where)

        else:
            self._seek(where, 2)

        if s is None:
            return self._read(1)

        else:
            return self._write(s)

    def _do_slice_contiguous(self, start, end, s=None):
        if start is None:
            start = 0

        if end is None:
            end = -1

        self._seek(start)
        if s is None:
            return self._read(end - start)

        else:
            return self._write(s)

    def _do_slice(self, where, s=None):
        if s is None:
            result = []
            for index in where:
                file._seek(index)
                result.append(file.read(1))

            return result

        else:
            for index, char in zip(where, s):
                file._seek(index)
                file._write(char)

            return len(s)

    def __getitem__(self, key):
        if isinstance(key, int):
            return self._do_single(key)

        elif isinstance(key, slice):
            if self._is_contiguous(key):
                return self._do_slice_contiguous(key.start, key.stop)

            else:
                return self._do_slice(self._process_slice(key))

        else:
            raise ValueError('File indices must be ints or slices.')

    def __setitem__(self, key, value):
        if isinstance(key, int):
            return self._do_single(key, value)

        elif isinstance(key, slice):
            if self._is_contiguous(key):
                return self._do_slice_contiguous(key.start, key.stop, value)

            else:
                where = self._process_slice(key)
                if len(where) == len(value):
                    return self._do_slice(where, value)

                else:
                    raise ValueError('Length of slice not equal to length of string to be written.')


    def __del__(self):
        self._file.close()

    def _is_contiguous(self, key):
        return key.step is None or key.step == 1

    def _process_slice(self, key):
        return range(key.start, key.stop, key.step)

    def _read(self, size):
        return self._file.read(size)

    def _seek(self, offset, whence=0):
        return self._file.seek(offset, whence)

    def _write(self, s):
        return self._file.write(s)

自从我匆忙完成这项工作以来,我确定可以做出很多优化,但是写起来很有趣。

这不能完全回答问题,因为它支持对字符的随机访问,就像对行的假定那样,行的抽象性更高,处理起来也更复杂(因为它们可以可变长度)