📜  Python代码的优化技巧

📅  最后修改于: 2022-05-13 01:55:18.585000             🧑  作者: Mango

Python代码的优化技巧

在这篇文章中,我们讨论了一些关于 Faster Python Code 的有趣的优化技巧。这些技术有助于在Python代码中更快地产生结果。

  1. 使用内置函数和库:像 map() 这样的内置函数是用 C 代码实现的。所以解释器不必执行循环,这会带来相当大的加速。
    map()函数将一个函数应用于 iterable 的每个成员并返回结果。如果有多个参数,则 map() 返回一个由元组组成的列表,其中包含来自所有可迭代项的相应项。
    # Python program to illustrate library functions
    # save time while coding with the example of map()
    import time
       
    # slower (Without map())
    start = time.clock() 
    s = 'geeks'
    U = []
    for c in s:
        U.append(c.upper())
    print (U)
    elapsed = time.clock()
    e1 = elapsed - start
    print ("Time spent in function is: ", e1)
       
    # Faster (Uses builtin function map())
    s = 'geeks'
    start = time.clock() 
    U = map(str.upper, s) 
    print (U)
    elapsed = time.clock()
    e2 = elapsed - start
    print ("Time spent in builtin function is: ", e2)
    

    输出:

    ['G', 'E', 'E', 'K', 'S']
    Time spent in function is:  0.0394747945637
    ['G', 'E', 'E', 'K', 'S']
    Time spent in builtin function is:  0.0212335531192
    
    

    这些包是特定于平台的,这意味着我们需要适合我们正在使用的平台的包。如果我们正在执行字符串操作,请考虑使用现有的模块“集合”,例如 deque,该模块已针对我们的目的进行了高度优化。

    # Python program to illustrate
    # importing list-like container with 
    # fast appends and pops on either end
    from collections import deque
    s = 'geek'
       
    # make a new deque
    d = deque(s)
       
    # add a new entry to the right side
    d.append('y')
       
    # add a new entry to the left side
    d.appendleft('h') 
    print (d)
       
    d.pop() # return and remove the rightmost item
       
    d.popleft() # return and remove the lefttmost item
       
    # print list deque in reverse
    print (list(reversed(d))) 
    

    输出:

    deque(['h', 'g', 'e', 'e', 'k', 'y'])
    ['k', 'e', 'e', 'g']
    
    # importing iteration tools
    import itertools
    iter = itertools.permutations([1,2,3])
    print (list(iter))
    

    输出:

    [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
    
  2. 使用键进行排序:在Python中,我们应该使用内置排序的键参数,这是一种更快的排序方式。
    # Python program to illustrate
    # using keys for sorting
    somelist = [1, -3, 6, 11, 5]
    somelist.sort()
    print (somelist)
      
    s = 'geeks'
    # use sorted() if you don't want to sort in-place:
    s = sorted(s)
    print (s)
    

    输出:

    [-3, 1, 5, 6, 11]
    ['e', 'e', 'g', 'k', 's']
    

    在每种情况下,列表都会根据您选择作为键参数的一部分的索引进行排序。这种方法与字符串一样适用于数字。

  3. 优化循环:编写惯用代码:这听起来可能违反直觉,但在大多数情况下,编写惯用代码会使您的代码更快。这是因为Python被设计为只有一种明显/正确的方式来完成任务。
    例如(字符串连接):
    # Python program to illustrate using
    # optimized loops for faster coding
      
    # slow O(n^2) - ( Note: In latest implementations it is O(n) )
    s = 'hellogeeks'
    slist = ''
    for i in s:
        slist = slist + i
    print (slist)
          
    # string concatenation (idiomatic and fast O(n))
    st = 'hellogeeks'
    slist = ''.join([i for i in s])
    print (slist)
      
    # Better way to iterate a range
    evens = [ i for i in range(10) if i%2 == 0]
    print (evens)
      
    # Less faster
    i = 0
    evens = []
    while i < 10:
        if i %2 == 0: 
            evens.append(i)
            i += 1
            print (evens)
      
    # slow
    v = 'for'
    s = 'geeks ' + v + ' geeks'
    print (s)
      
    # fast
    s = 'geeks %s geeks' % v
    print (s)
      
      
    

    输出:

    hellogeeks
    [0, 2, 4, 6, 8]
    geeks for geeks
    

    每次对 s(i) 运行循环时, Python都会评估该方法。但是,如果将评估放在变量中,则该值是已知的, Python可以更快地执行任务。

  4. 尝试多种编码方法:每次创建应用程序时使用完全相同的编码方法几乎肯定会导致某些情况下应用程序运行得比它可能运行得慢。
    例如(初始化字典元素):
    # Python program to illustrate trying
    # multiple coding approaches 
    # for getting faster result
    # slower
    mydict = {'g':1,'e':1,'e':1,'k':1}
    word = 'geeksforgeeks'
    for w in word:
        if w not in mydict:
            mydict[w] = 0
        mydict[w] += 1
    print (mydict)
      
    # faster
    mydict = {'g':1,'e':1,'e':1,'k':1}
    word = 'geeksforgeeks'
    for w in word:
        try:
            mydict[w] += 1
        except KeyError:
            mydict[w] = 1
    print (mydict)
    

    输出:

    {'e': 5, 'g': 3, 'f': 1, 'k': 3, 'o': 1, 's': 2, 'r': 1}
    

    两种情况下的输出是相同的。唯一的区别是如何获得输出。

  5. 使用 xrange 代替 range: range() - 这将返回使用 range()函数创建的数字列表。
    xrange() – 此函数返回生成器对象,该生成器对象只能通过循环来显示数字。仅按需显示特定范围,因此称为“惰性评估”。
    # slower
    x = [i for i in range(0,10,2)]
    print (x)
      
    # faster
    x = [i for i in range(0,10,2)]
    print (x)
    

    输出:

    [1, 3, 5, 7, 9]
    

    这可以节省您的系统内存,因为 xrange() 一次只会产生一个序列中的一个整数元素。而 range(),它为您提供了一个完整的列表,这对于循环来说是不必要的开销。

  6. 使用Python多重赋值来交换变量:这在Python中既优雅又快捷。
    # Python program to illustrate swapping
    # of a variable in one line 
      
    # slower
    x = 2
    y = 5
    temp = x
    x = y
    y = temp
    print (x,y)
      
    x,y = 3,5
    # faster
    x, y = y, x
    print (x,y)
    

    输出:

    5 2
    5 3
    
  7. 尽可能使用局部变量: Python检索局部变量比检索全局变量更快。也就是说,避免使用“全局”关键字。因此,如果您要经常(在循环内)访问一个方法,请考虑将其写入一个变量。
    # Python program to illustrate trying
    # to use local variables to make code
    # run faster
    class Test:
        def func(self,x):
            print (x+x)
      
    # Declaring variable that assigns class method object
    Obj = Test()
    mytest = Obj.func # Declaring local variable
    n = 2
    for i in range(n):
        mytest(i) # faster than Obj.func(i)
    

    输出:

    0
    2
    


参考:

  • 堆栈溢出
  • Python.org