存储函数而不调用它们

时间:2018-02-05 19:37:27

标签: python function generator

我有一个模块,它具有生成序列的功能。物品很长。然后,我有特定的序列名称,将生成与该名称相关联的特定项目集。我的问题是我不希望模块在定义期间实际构建所有序列,但只有在调用该名称时才构建它。我目前的方案是这样的(实际gen_sequence函数要复杂得多,但想法仍然相同):

def gen_sequence(start, end):
    return list(range(start, end))

def gen_sequence_scalar(start, end, scalar):
    return [x * scalar for x in range(start, end)]

def SEQUENCE_10():
    return gen_sequence(0, 10)

def SEQUENCE_100():
    return gen_sequence(0, 100)

def BIG_SEQUENCE():
    return gen_sequence(0, 1000) + gen_sequence_scalar(10000, 50000, 3)

mapper = {
    'Small Sequence': SEQUENCE_10,
    'Medium Sequence': SEQUENCE_100,
    'Big Sequence': BIG_SEQUENCE,
    }

现在,用户可以使用序列名称来检索生成器,然后可以根据实际序列对其进行评估。

s = mapper['Big Sequence']()

这种方法的主要问题是,对于命名mapper中的每个新命名序列,我必须专门为该生成器创建一个函数。像'Big Sequence'这样的序列是多个序列生成器的串联,所以如果我把它们放在mapper字典中,它会在定义时对它们进行评估,这是我不想要的。有没有更好的方法,或者为每个命名的生成器创建一个函数,然后像我这样的映射字典有最好的方法来做到这一点?

2 个答案:

答案 0 :(得分:2)

您真的需要这些序列成为实际列表吗?在许多情况下,您真正​​需要的只是一台能产生所需数字的发电机。这比构建实际列表要紧凑得多,如果你需要一个实际的列表,你可以将生成器传递给list构造函数。

我已经修改了你的mapper dict,这样它现在不存储函数,而是存储args列表以传递给range构造函数。在itertools.chain的帮助下,我的sequence函数使用这些参数构建匹配的生成器。

from itertools import chain

mapper = {
    'Small Sequence': [(5,)], 
    'Medium Sequence': [(10, 20, 2)], 
    'Big Sequence': [(30, 40), (50, 60)],
}

def sequence(name):
    args = mapper[name]
    return chain.from_iterable(range(*a) for a in args)

# test

for u in sequence('Small Sequence'):
    print(u)

for k in mapper:
    print(k, list(sequence(k)))

<强>输出

0
1
2
3
4
Small Sequence [0, 1, 2, 3, 4]
Medium Sequence [10, 12, 14, 16, 18]
Big Sequence [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]

答案 1 :(得分:2)

您可以使用lambdas而不是创建许多仅在此处使用的命名函数。

mapper = {
    'Small Sequence': lambda: gen_sequence(10),
    'Medium Sequence': lambda: gen_sequence(100),
    'Big Sequence': lambda: gen_sequence(1000) + gen_sequence(1000000)
}