Are list-comprehensions and functional functions faster than “for loops”?

后端 未结 7 1441
梦如初夏
梦如初夏 2020-11-22 01:48

In terms of performance in Python, is a list-comprehension, or functions like map(), filter() and reduce() faster than a for loop? Why

7条回答
  •  梦谈多话
    2020-11-22 02:12

    You ask specifically about map(), filter() and reduce(), but I assume you want to know about functional programming in general. Having tested this myself on the problem of computing distances between all points within a set of points, functional programming (using the starmap function from the built-in itertools module) turned out to be slightly slower than for-loops (taking 1.25 times as long, in fact). Here is the sample code I used:

    import itertools, time, math, random
    
    class Point:
        def __init__(self,x,y):
            self.x, self.y = x, y
    
    point_set = (Point(0, 0), Point(0, 1), Point(0, 2), Point(0, 3))
    n_points = 100
    pick_val = lambda : 10 * random.random() - 5
    large_set = [Point(pick_val(), pick_val()) for _ in range(n_points)]
        # the distance function
    f_dist = lambda x0, x1, y0, y1: math.sqrt((x0 - x1) ** 2 + (y0 - y1) ** 2)
        # go through each point, get its distance from all remaining points 
    f_pos = lambda p1, p2: (p1.x, p2.x, p1.y, p2.y)
    
    extract_dists = lambda x: itertools.starmap(f_dist, 
                              itertools.starmap(f_pos, 
                              itertools.combinations(x, 2)))
    
    print('Distances:', list(extract_dists(point_set)))
    
    t0_f = time.time()
    list(extract_dists(large_set))
    dt_f = time.time() - t0_f
    

    Is the functional version faster than the procedural version?

    def extract_dists_procedural(pts):
        n_pts = len(pts)
        l = []    
        for k_p1 in range(n_pts - 1):
            for k_p2 in range(k_p1, n_pts):
                l.append((pts[k_p1].x - pts[k_p2].x) ** 2 +
                         (pts[k_p1].y - pts[k_p2].y) ** 2)
        return l
    
    t0_p = time.time()
    list(extract_dists_procedural(large_set)) 
        # using list() on the assumption that
        # it eats up as much time as in the functional version
    
    dt_p = time.time() - t0_p
    
    f_vs_p = dt_p / dt_f
    if f_vs_p >= 1.0:
        print('Time benefit of functional progamming:', f_vs_p, 
              'times as fast for', n_points, 'points')
    else:
        print('Time penalty of functional programming:', 1 / f_vs_p, 
              'times as slow for', n_points, 'points')
    

提交回复
热议问题