如何延迟加载数据结构(python)

Ant*_*nko 8 python lazy-loading

我有一些构建数据结构的方法(比如说某些文件内容):

def loadfile(FILE):
    return # some data structure created from the contents of FILE
Run Code Online (Sandbox Code Playgroud)

所以我可以做的事情

puppies = loadfile("puppies.csv") # wait for loadfile to work
kitties = loadfile("kitties.csv") # wait some more
print len(puppies)
print puppies[32]
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我浪费了大量时间实际阅读kitties.csv和创建一个我从未使用过的数据结构.我想在没有经常检查的情况下避免浪费if not kitties.我希望能够做到

puppies = lazyload("puppies.csv") # instant
kitties = lazyload("kitties.csv") # instant
print len(puppies)                # wait for loadfile
print puppies[32]
Run Code Online (Sandbox Code Playgroud)

因此,如果我不尝试做任何事情kitties,loadfile("kitties.csv")永远不会被召唤.

有没有一些标准的方法来做到这一点?

在玩了一下后,我制作了以下解决方案,它似乎工作正常并且非常简短.还有其他选择吗?使用这种方法是否有缺点我应该记住?

class lazyload:
    def __init__(self,FILE):
        self.FILE = FILE
        self.F = None
    def __getattr__(self,name):
        if not self.F: 
            print "loading %s" % self.FILE
            self.F = loadfile(self.FILE)
        return object.__getattribute__(self.F, name)
Run Code Online (Sandbox Code Playgroud)

可能更好的是,如果这样的事情有效:

class lazyload:
    def __init__(self,FILE):
        self.FILE = FILE
    def __getattr__(self,name):
        self = loadfile(self.FILE) # this never gets called again
                                   # since self is no longer a
                                   # lazyload instance
        return object.__getattribute__(self, name)
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为self是本地的.它实际上最终会在loadfile你每次做任何事情时都打电话.

Len*_*bro 5

Python stdlibrary 中的 csv 模块在您开始迭代数据之前不会加载数据,因此它实际上是惰性的。

编辑:如果您需要通读整个文件来构建数据结构,那么拥有一个复杂的延迟加载对象来代理事物是多余的。只需这样做:

class Lazywrapper(object):
    def __init__(self, filename):
        self.filename = filename
        self._data = None

    def get_data(self):
        if self._data = None:
            self._build_data()
        return self._data

    def _build_data(self):
        # Now open and iterate over the file to build a datastructure, and
        # put that datastructure as self._data
Run Code Online (Sandbox Code Playgroud)

使用上面的类,您可以执行以下操作:

puppies = Lazywrapper("puppies.csv") # Instant
kitties = Lazywrapper("kitties.csv") # Instant

print len(puppies.getdata()) # Wait
print puppies.getdata()[32] # instant
Run Code Online (Sandbox Code Playgroud)

allkitties = kitties.get_data() # wait
print len(allkitties)
print kitties[32]
Run Code Online (Sandbox Code Playgroud)

如果你有很多数据,而且你真的不需要加载所有数据,你也可以实现类似类的东西,它会读取文件,直到它找到名为“Froufrou”的小狗,然后停止,但此时它是最好将数据一劳永逸地保存在数据库中并从那里访问它。