Python 仅在调用字典键时生成数据

Python 仅在调用字典键时生成数据,python,function,dictionary,Python,Function,Dictionary,我正在努力使我的程序更有效率。我有一个包含大量数据序列的模块。目前,它是一个键值对字典,表示序列名(key)和作为值附加在一起的多个生成器函数。例如: sequences = { 'One' = make_items(100000) + make_other_items(20) 'Two' = make_items(9393) } 现在让我们假设make_items生成n个随机字符串,n是作为参数提供的整数。随着序列数量的增加,如果我在程序执行期间只需要在字典中存储一个

我正在努力使我的程序更有效率。我有一个包含大量数据序列的模块。目前,它是一个键值对字典,表示序列名(key)和作为值附加在一起的多个生成器函数。例如:

sequences = {
    'One' = make_items(100000) + make_other_items(20)
    'Two' = make_items(9393)
    }
现在让我们假设make_items生成n个随机字符串,n是作为参数提供的整数。随着序列数量的增加,如果我在程序执行期间只需要在字典中存储一个项目的值,这可能会严重影响处理和内存。如果
sequences
位于模块的全局命名空间中,则在导入模块时将加载所有内容,并始终将其存储在内存中。如果我把字典放在一个函数中,并返回我调用的值,内存问题就解决了,但是当调用包装器函数时,它仍然会计算字典中每个项的每个值——效率也不高

我的想法是为全局命名空间中的每个值创建一个函数,然后在调用一个项后使用映射器字典实际运行该函数。我想知道这是否是最干净的方法,因为它确实增加了代码的复杂性,并且必须确保变量和字符串在多个位置正确拼写

sequences = [
    'Sequence One',
    'Sequence Two',
    'Sequence Three',

def SEQUENCE_ONE():
    data = make_items(100000) + make_other_items(20)
    return data

def SEQUENCE_TWO():
    data = make_items(9393)
    return data

def SEQUENCE_THREE():
    data = make_other_items(4)
    return data

def mapper(name):
    map = {
        'Sequence One': SEQUENCE_ONE,
        'Sequence Two': SEQUENCE_TWO,
        'Sequence Three': SEQUENCE_THREE
        }
    data = map[name]()
    return name, data

这是最干净、最简单的解决方案,还是有更好的方法来实现数据的动态生成?

通过子类化
defaultdict
,为您提供一个更具python风格的替代方案:

from collections import defaultdict

def make_items(n):
    print('making {} items...'.format(n))
    return range(n)

class LazyDict(defaultdict):
    def __missing__(self, k):
        self[k] = make_items(k)
        return self[k]

sequences = LazyDict()
它仅在首次使用时生成值:

>>> sequences = LazyDict()
>>> sequences[10]
making 10 items...
range(0, 10)
>>> sequences[10]
range(0, 10)

如果键不在
{'Sequence One'、'Sequence Two'、'Sequence Two'、'Sequence Two'}

中,您可以很容易地调整
\uuuu missing\uuuu
的实现,以引发
keyrerror
,因为Python首先计算右侧的表达式。但是,您可以构造某种惰性字典,并将函数而不是实际值传递给它。这些函数会在需要的时候被计算出来。这听起来像是一个很好的用例。会有帮助吗?@WillemVanOnsem感谢你指出这一点-我修改了代码,实际调用了映射中请求的函数。我现在所做的应该是可行的,因为map dict只存储函数引用,然后在mapper函数中指定数据变量时,只计算所述函数。除非我遗漏了其他东西?这看起来几乎可以用了——但我不确定如何使它适应我的用例。如果您看一下我的示例代码,每个序列都以特定于该序列名称的不同顺序使用不同的生成器函数,因此每个序列名称都需要在某个地方定义该序列所需的确切函数调用。这是否可以调整?是的,因此您可以从
\uuuu missing\uuuu
内部调用函数。试试看,我把那部分留给你。