这个问题基于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)
答案 0 :(得分: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