Python 定义变量为 "load file at first use"

Python define variable as "load file at first use"

Python 初学者。我目前有一些代码看起来像

a=some_file_reading_function('filea')
b=some_file_reading_function('fileb')
# ...
if some_condition(a):
    do_complicated_stuff(b)
else:
    # nothing that involves b

令我恼火的是 'fileb' 的负载可能不是必需的,而且它有一些性能损失。理想情况下,只有在以后实际需要 b 时,我才会加载它。 OTOH, b 可能被多次使用,所以如果它被使用一次,它应该加载一次文件。我不知道如何实现。

在上面的伪代码中,可以简单地将 'fileb' 的加载带入条件循环中,但实际上有两个以上的文件并且条件分支非常复杂。此外,代码仍在大量开发中,条件分支可能会更改。

我看了看迭代器或定义 class,但(可能是由于我缺乏经验)无法使任何一个工作。我遇到的关键问题是如果不需要则零次加载文件,如果需要则只加载一次。我在搜索时一无所获,因为 "how to load a file by chunks" 污染了 "file lazy loading" 和类似查询的结果。

如果需要:Python Win7 上的 3.5,以及 some_file_reading_function returns 1D- numpy.ndarray 的。

class LazyFile():
  def __init__(self, file):
    self.file = file
    self._data = None

  @property # so you can use .data instead of .data()
  def data(self):
    if self._data is None: # if not loaded
      self._data = some_file_reading_function(self.file) #load it

    return self._data

a = LazyFile('filea')
b = LazyFile('fileb')

if some_condition(a.data):
  do_complicated_stuff(b.data)
else:
  # other stuff

实际上,刚刚找到了 类 的解决方法。 Try/except 灵感来自 How to know if an object has an attribute in Python。有点难看,但够用了:

class Filecontents:
    def __init__(self,filepath):
        self.fp = filepath
    def eval(self):
        try:
            self.val
        except AttributeError:
            self.val = some_file_reading_function(self.fp)
            print(self.txt)
        finally:
            return self.val
def some_file_reading_function(fp):
    # For demonstration purposes: say that you are loading something
    print('Loading '+fp)

    # Return value
    return 0


a=Filecontents('somefile')
print('Not used yet')
print('Use #1: value={}'.format(a.eval()))
print('Use #2: value={}'.format(a.eval()))

虽然不确定这是 "best"(最漂亮、最 Pythonic)的解决方案。