2012-07-12 95 views
9

哪个更好?使用if/else或dictionary的更好的优化技巧

  • 一系列接收'string'的if/else语句为其返回相应的函数。 (大约40-50条if/else语句)。
  • 维护键值对的字典。键作为字符串,值作为函数对象,以及一个用于搜索和返回函数对象的主函数。

实际上使用上述方法返回函数对象的主函数被称为数百万或数十亿次,所以需要智能地做到这一点。有什么更好的办法?

例如,

dict['str1'] = func1 
dict['str2'] = func2 
and so on.. 

def main_func(str): 
    return dict[str] 

或者

def main_func(str): 
    if 'str1': 
     return func1 
    elif 'str2': 
     return func2 

这将是更好的..?如果我们有50-60个这样的字符串,并且这个过程需要数十亿次。

存储内部词典功能对象,在函数本身: -

def func1(): 
    if dict.has_key('str1'): 
     dict['str1'] = func1 
    -- do something -- 

哪个更好,这或上述之一。这看起来更干净。但请记住,这些函数会被调用很多次,所以has_key函数也会被多次调用。

感谢

+10

写入和** **他们**。 – huon 2012-07-12 05:01:07

+2

我与字典一起去,而不是首先检查键是否在字典中只是有一个函数来执行需要做的事情,如果字符串丢失并返回dict.get(string,string_missing_function) – Paddy3118 2012-07-12 06:34:19

+0

好的调用!每天都要学习新的东西,我已经将自己的想法融入了我的文章。这开始显示function_lookup甚至不需要定义! – 2012-07-12 06:39:08

回答

12

选择字典。

The dictionary ...

  • 是内置
  • 是Python的
  • 需要较少的样板代码
  • 已O(1)的复杂性,相比于如果其他线性O(n)的复杂性
  • 不犯过早pessimization的(我们有足够的理由相信不用分析,这是一个低效率的方法,以大比分)

我建议写解决方案首先使用字典并查看解决方案是否足够满足您的需求。如果是这样,很好,你完成了。如果不是,则反其道而行。

考虑这样一个解决方案(将返回None如果没有找到该字符串):

func_dict = {} 
func_dict['str1'] = fun1 
func_dict['str2'] = fun2 
... 
def function_lookup(func_string): 
    return func_dict.get(func_string) 

然后,在你的主,只是写function_lookup(whatever_string_variable)尝试查找你的功能。这样可以避免每次调用function_lookup时重建字典。

+0

嗯,我应该将函数对象存储在函数本身内部,还是仅在主函数内部执行它,以上是例子。 – geek 2012-07-12 05:22:31

+0

只要你没有在循环中定义函数,你应该很好。 – 2012-07-12 05:24:07

+0

这将是...该函数将被调用多次....所以has_key函数将被调用,??我对吗..? – geek 2012-07-12 05:26:09

2

从技术上讲,这取决于哈希冲突的表现,但我想存储在哈希中的所有数据和检索这将是稍快

在任何情况下,差异可能都不会很大。当然,哈希表解决方案更清洁,所以我会建议。

确切知道的最好方法是编写两个版本,并用大量数据测试它们并测量它们的性能。

1

词典更好。字典应该由树/散列表支持,并且比if-else语句(大致线性)具有更好的时间复杂度。即使实际运行时间并不好,代码也会随着字典变得更清晰。

1

字典是蟒蛇的重点调整部分之一。他们产生更多可读代码。 他们应该比你的if循环执行得更好。 但是,考虑到插入和其他开销,我建议你使用timeit模块并检查性能。

6

字典将更快:它大约是O(1),而if语句的链是O(n)。为了证明,这个脚本(make_test.py)将输出运行一些peformance测试Python脚本:

ifs = [] 
dict = [] 
for i in range(60): 
    string = 'str%d' % i 
    ifs.append(' %sif str == "%s": return %d' % ('el' if i else '', string, i)) 
    dict.append('"%s": %d' % (string, i)) 

print 'dict = {', ','.join(dict), '}' 
print 'def with_dict(str):' 
print ' return dict[str]' 

print 'def with_if(str):' 
print '\n'.join(ifs) 

print ''' 
import timeit 

def test_dict(): 
    for i in range(60): 
     with_dict("str%d" % i) 

def test_if(): 
    for i in range(60): 
     with_if("str%d" %i) 

print 'dict:', timeit.timeit(test_dict, number=10000) 
print 'if: ', timeit.timeit(test_if, number=10000)''' 

python make_test.py | python运行它,给我:

dict: 0.706176042557 
if: 1.67383503914 

也就是说,if版本超过比dict版本慢2倍。

+3

不要猜测,测量! +1为您的结果。 :-) – Paddy3118 2012-07-12 06:28:33

+0

您的比较遗漏了构建字典所需的时间,这并非无关紧要,在许多情况下,如果用作if语句的替代品,则不会缓存该字典。 – Silfheed 2014-01-14 00:38:00

+0

可能对某人有用:如果测试条件不变/常量(使用字符串存储代码以便后面的eval()/ exec()),则使用映射,否则使用if-else。使用全局作用域,关闭或关键字参数(快速入侵和安全漏洞)来缓存映射。 – 8day 2016-03-14 10:04:22

0

dict lookup的平均时间复杂度为O(1)。最坏的情况是O(n)。只有str键的字典才有优化(您的用例)。

假设if/else梯形图中测试的顺序本身不能根据输入的频率进行优化(例如60个可能性,其中2个发生在95%的时间内),但是一系列if/else语句是O(n)。

因此字典会提供更好的性能以及更好的代码可读性。

0

哪个解决方案看起来更优雅,更容易维护。

在大多数应用程序设计中,优化人工时间和可维护性更重要,那么就是优化计算机时间。电脑时间便宜。人类的时间很昂贵。

这两种解决方案都有其优点。

如果您需要稍后添加控制流,如if/else嵌套,if/elif解决方案可能会提供更大的灵活性。

如果数据直接来自像yaml或数据库这样的数据源,那么字典解决方案显然更加优雅。