Python 使用if/else或dictionary的更好的优化技术

Python 使用if/else或dictionary的更好的优化技术,python,algorithm,Python,Algorithm,哪一种优化更好 接收“string”的一系列if/else语句返回相应的函数。(大约40-50个if/else语句) 维护键值对的字典。键作为字符串,值作为函数对象,一个主函数用于搜索和返回函数对象 使用上述方法实际返回函数对象的主函数将被调用数百万次或数十亿次,因此需要智能地执行此操作。还有什么更好的办法 例如 dict['str1'] = func1 dict['str2'] = func2 and so on.. def main_func(str): return dict

哪一种优化更好

  • 接收“string”的一系列if/else语句返回相应的函数。(大约40-50个if/else语句)
  • 维护键值对的字典。键作为字符串,值作为函数对象,一个主函数用于搜索和返回函数对象
使用上述方法实际返回函数对象的主函数将被调用数百万次或数十亿次,因此需要智能地执行此操作。还有什么更好的办法

例如

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

def main_func(str):
    return dict[str]

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

在字典中存储函数对象,在函数本身中:-

def func1():
   if dict.has_key('str1'):
        dict['str1'] = func1
   -- do something --
哪个更好,这个还是上面那个。这看起来干净多了。?但请记住,这些函数会被多次调用,所以has_key函数也会被多次调用


从技术上说,这取决于散列冲突性能,但我可以想象,将所有数据存储在散列中并检索它会稍微快一点

在任何情况下,两者之间的差异可能都不会很大。当然,哈希表解决方案更干净,所以我建议这样做


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

字典更好。字典应该由树/哈希映射支持,并且比if-else语句(大致是线性的)具有更好的时间复杂度。即使实际运行时间不是更好,使用dictionary,代码也会更干净。

选择dictionary

字典

  • 是内置的
  • 是肾盂的
  • 需要更少的样板代码
  • 与if-else线性O(n)复杂度相比,具有O(1)复杂度
  • 没有过早悲观的罪过(我们没有足够的理由相信这是一种效率较低的方法,而不进行分析)
我建议先使用字典编写解决方案,看看该解决方案是否足够快,满足您的需要。如果是这样,太好了,你完了。如果没有,则以相反的方式计时

考虑这样的解决方案(如果找不到字符串,将返回
None
):


然后,在main中,只需编写
function\u lookup(无论什么字符串\u变量)
即可尝试查找函数。这避免了每次调用
函数\u lookup
时都重新生成字典。

字典是python中经过大量调优的部分之一。它们产生更可读的代码。 它们的性能应该比if循环更好。
但是,考虑到插入和其他开销,我建议您使用timeit模块并检查性能。

字典将更快:大约为O(1),而if语句链为O(n)。为了演示,此脚本(
make_test.py
)将输出一个运行一些性能测试的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倍以上。

的平均时间复杂度为O(1)。最坏的情况是O(n)。对于只使用str键的字典(您的用例),有一些优化

假设if/else梯形图中的测试顺序本身无法根据输入频率进行优化(例如,60种可能性,其中2种发生率为95%),则一系列if/else语句的复杂性为O(n)


因此,字典将提供更好的性能和更好的代码可读性。

每个解决方案看起来都更优雅,更易于维护

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

两种解决方案都有各自的优势

如果以后需要添加控制流(如嵌套的if/else),if/elif解决方案可以提供更大的灵活性


如果数据直接来自yaml或数据库等数据源,则dict解决方案显然更为优雅。

编写这两个数据并对其进行分析。我使用字典,但不是首先检查键是否在dict中,而是使用一个函数来执行在字符串丢失时需要执行的操作并返回dict.get(字符串,字符串\缺少\函数)好主意!每天学习一些新的东西,我已经把你的一点加入到我的帖子中。这开始表明,函数查找甚至不需要定义!对于较小的列表,if-else会更快,但随着大小的增长,dictionary会更快。总的来说,dictionary会更好。但我猜switch case会比它们都好(python缺少)!嗯,我应该将函数对象存储在函数本身中,还是只在主函数中执行,上面写了一个例子。只要你不在循环中定义函数,你就应该是好的。这将是…函数将被多次调用…因此将调用is has_key函数,?我说得对吗?现在看看我的编辑。进行编辑请确保为函数提供了良好的描述性名称,这样您就不会忘记所有操作。还要避免使用内置变量名或已定义的内容,如
dict
。谢谢兄弟,还有一件事..我应该如何选择字符串(str1,str2)…现在它们是随机的..将str1、str2、str3或h1、h2、h3映射到原始字符串是否会产生更好的结果,或者任何随机字符串也会产生更好的性能..?不要猜测,测量!+1作为结果。:-)您的比较忽略了构建字典需要时间这一事实,它不是无关紧要的,在许多情况下,当用作if语句的替换时,它不会被缓存
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)'''
dict: 0.706176042557
if:   1.67383503914