How are deques in Python implemented, and when are they worse than lists?

后端 未结 5 1703
南方客
南方客 2020-11-28 04:48

I\'ve recently gotten into investigating how various data structures are implemented in Python in order to make my code more efficient. In investigating how lists and deques

5条回答
  •  臣服心动
    2020-11-28 05:26

    Check out collections.deque. From the docs:

    Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.

    Though list objects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs for pop(0) and insert(0, v) operations which change both the size and position of the underlying data representation.

    Just as it says, using pop(0) or insert(0, v) incur large penalties with list objects. You can't use slice/index operations on a deque, but you can use popleft/appendleft, which are operations deque is optimized for. Here is a simple benchmark to demonstrate this:

    import time
    from collections import deque
    
    num = 100000
    
    def append(c):
        for i in range(num):
            c.append(i)
    
    def appendleft(c):
        if isinstance(c, deque):
            for i in range(num):
                c.appendleft(i)
        else:
            for i in range(num):
                c.insert(0, i)
    def pop(c):
        for i in range(num):
            c.pop()
    
    def popleft(c):
        if isinstance(c, deque):
            for i in range(num):
                c.popleft()
        else:
            for i in range(num):
                c.pop(0)
    
    for container in [deque, list]:
        for operation in [append, appendleft, pop, popleft]:
            c = container(range(num))
            start = time.time()
            operation(c)
            elapsed = time.time() - start
            print "Completed %s/%s in %.2f seconds: %.1f ops/sec" % (container.__name__, operation.__name__, elapsed, num / elapsed)
    

    Results on my machine:

    Completed deque/append in 0.02 seconds: 5582877.2 ops/sec
    Completed deque/appendleft in 0.02 seconds: 6406549.7 ops/sec
    Completed deque/pop in 0.01 seconds: 7146417.7 ops/sec
    Completed deque/popleft in 0.01 seconds: 7271174.0 ops/sec
    Completed list/append in 0.01 seconds: 6761407.6 ops/sec
    Completed list/appendleft in 16.55 seconds: 6042.7 ops/sec
    Completed list/pop in 0.02 seconds: 4394057.9 ops/sec
    Completed list/popleft in 3.23 seconds: 30983.3 ops/sec
    

提交回复
热议问题