Generic Lazy属性getter / setter

问题描述 投票:0回答:1

这个问题基于this question关于python类的惰性属性。

我真的很喜欢那里的解决方案:

这是一个惰性属性装饰器的示例实现:

import functools

def lazyprop(fn):
    attr_name = '_lazy_' + fn.__name__

    @property
    @functools.wraps(fn)
    def _lazyprop(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, fn(self))
        return getattr(self, attr_name)

    return _lazyprop


class Test(object):

    @lazyprop
    def a(self):
        print 'generating "a"'
        return range(5)

互动环节:

>>> t = Test()
>>> t.__dict__
{}
>>> t.a
generating "a"
[0, 1, 2, 3, 4]
>>> t.__dict__
{'_lazy_a': [0, 1, 2, 3, 4]}
>>> t.a
[0, 1, 2, 3, 4]

此解决方案允许您为任何属性创建@lazyprop。但是,您必须为希望延迟的每个属性编写一个方法。我需要的东西适用于我的名字我不会提前知道的属性(其中可能有很多)。

这些属性是从hdf5文件读入的DataFrame。每个文件都包含许多不同的表,我不知道这些表的名称。我有一个很好的函数,get_all_table_names(filename)返回文件中所有表的名称。目前,我遍历所有名称,并一个接一个地阅读它们。但是,有几十GB的数据,需要几分钟才能读入。

当方法调用该表时,有没有办法只在表中实际读取?这里给出的例子是完美的,除了我需要提前知道表的名称。

编辑

将数据从HDF5文件加载到Pandas DataFrame的代码如下所示。

df = read_to_pandas(directory_of_files, 'table_name', number_of_files_to_read)
python lazy-loading
1个回答
0
投票

这是一个通用模板,展示了如何使用动态延迟属性动态生成类:

import functools
import types


def lazyprop(added_value):
    """ Slightly generalize lazy attribute property decorator.
        (i.e. a decorator-factory)
    """
    def prop(fn):
        attr_name = '_lazy_' + fn.__name__ + str(added_value)

        @property
        @functools.wraps(fn)
        def _lazyprop(self):
            if not hasattr(self, attr_name):
                setattr(self, attr_name, fn(self, added_value))
            return getattr(self, attr_name)

        return _lazyprop

    return prop


def make_class(class_name, attrs):

    # Generic methods and class __dict__.
    def __init__(self):
        print('creating instance of class', self.__class__.__name__)

    def getter(self, added_value):
        return 41 + added_value

    cls_dict = {
        '__init__': __init__,
        '__repr__': lambda self: 'class name: %s' % class_name,
    }

    # Create and added lazy attributes.
    for i, attr_name in enumerate(attrs):
        cls_dict[attr_name] = lazyprop(i)(getter)

    cls = types.new_class(class_name, (), {}, lambda ns: ns.update(cls_dict))
    cls.__module__ = __name__

    return cls


if __name__ == '__main__':

    Foobar = make_class('Foobar', ('attr1', 'attr2'))

    foobar = Foobar()    # -> creating instance of class Foobar
    print(foobar)        # -> class name: Foobar
    print(foobar.attr1)  # -> 41
    print(foobar.attr2)  # -> 42
© www.soinside.com 2019 - 2024. All rights reserved.