我有一个模块,它具有生成序列的功能。物品很长。然后,我有特定的序列名称,将生成与该名称相关联的特定项目集。我的问题是我不希望模块在定义期间实际构建所有序列,但只有在调用该名称时才构建它。我目前的方案是这样的(实际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字典中,它会在定义时对它们进行评估,这是我不想要的。有没有更好的方法,或者为每个命名的生成器创建一个函数,然后像我这样的映射字典有最好的方法来做到这一点?
答案 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)
}