pythonappend性能_python的list添加新元素的操作效率比较

List是python中比较常用的数据类型,一般向list添加元素有如下四种方法(append,extend,insert,+),自己写了个简单方法,向一个空的list添加3千万个相同元素,比较了下这四种方法的效率:

import time

def append(n):

a=[]

for i in range(n):

a.append(1)

def insert(n):

b=[]

for i in range(n):

b.insert(i, 1)

def extend(n):

c=[]

for i in range(n):

c.extend((1,))

def sum(n):

d=[]

list = [1]

for i in range(n):

list1 = d + list

num = 30000000

intervall1 = time.time()

append(num)

print('append',time.time()-intervall1)

intervall2 = time.time()

insert(num)

print('insert',time.time()-intervall2)

intervall3 = time.time()

extend(num)

print('extend',time.time()-intervall3)

intervall4 = time.time()

sum(num)

print('sum',time.time()-intervall4)

运行结果:

(sum代表+方法,下面简称sum)

append 2.937000036239624(秒)

insert 5.21399998664856(秒)

extend 2.991000175476074(秒)

sum 2.7809998989105225(秒)

从结果看来sum的效率最高,insert效率最低,append和extend效率基本一致。

1.首先sum方法不同于前三种方法,前三种方法添加元素时是在原来的list对象进行操作,他们没有返回值。而sum方法是将两个list对象连接,生成一个新的list对象,从而消耗额外的内存。(对于io密集型应用不建议用该方法,况且针对append方法来说效率提升有限)

2. append() 追加单个元素到List的尾部,只接受一个参数,参数可以是任何数据类型,被追加的元素在List中保持着原结构类型。此元素如果是一个list,那么这个list将作为一个整体进行追加,注意append()和extend()的区别。

>>> list1=['a','b']

>>> list1.append('c')

>>> list1

['a', 'b', 'c']

3.extend() 将一个列表中每个元素分别添加到另一个列表中,只接受一个参数;extend()相当于是将list B 连接到list A上。

>>> list1

['a', 'b', 'c']

>>> list1.extend('d')

>>> list1

['a', 'b', 'c', 'd']

4.insert() 将一个元素插入到列表中,但其参数有两个(如insert(1,”g”)),第一个参数是索引点,即插入的位置,第二个参数是插入的元素。

>>> list1

['a', 'b', 'c', 'd']

>>> list1.insert(1,'x')

>>> list1

['a', 'x', 'b', 'c', 'd']

为什么人们普遍说append效率要高于insert,因为Python中的列表并不是传统意义上的列表,这也是Python中列表的append操作比insert操作高效的根本原因。传统意义上的列表,通常叫做链表,是通过一系列的节点来实现的,每个节点(尾节点除外)都有一个指向下一个节点的指针。简单单向链表(双向链表多一个指向前一个节点的指针)实现如下:

class Node:

def __init__(self,value,next=Node)

self.value=value

self.next=next

将节点构造成列表:

>>>L=Node("a",Node("b",Node("c",Node("d"))))

>>>L.next.next.value

'c'

但是Python中的列表则与此不同。它不是由若干个独立的节点相互引用而组成的,而是一整块单一连续的内存区块--我们通常称之为数组。这直接导致其与链表之间的一些区别。例如,尽管两者在遍历时的效率相差无几(除了链表有一些额外开销),但是如果我们按照既定索引值对某元素进行直接访问的话,显然使用数组会更加的高效。因为在数组中,我们通常可以直接计算出目标元素在内存中的位置,并对其进行直接访问。而对于链表,我们需要从头开始遍历整个链表。

但是对于insert操作来说,情况又有所不同。对于链表而言,只要知道了在哪里执行insert操作,其操作成本是非常低的。无论该链表中有多少元素,其操作时间大致相同。但是,对于数组而言,每次执行insert操作都需要移动插入点右边所有的元素,甚至在必要时需要把所有数组元素复制到另外一个更大的数组中。也正因如此,append操作通常会采用一种被称为动态数组或向量的特定解决方案。其主要思路是将内存分配的过大一些,并且等到其溢出时,在线性时间内再次重新分配内存。但这样做似乎会使得append操作变得跟insert操作一样糟糕。其实不然,因为尽管这两种情况会迫使我们去搬动大量的元素,但主要的不同点在于,对于append操作,发生这样的可能性要小得多。事实上,只要我们能确保每次所搬入的数组都大过原数组一定的比例(例如20%甚至100%),那么该操作的平均成本(或者说的更确切一些,将这些搬运开销均摊到每次append操作中去)通常是常数的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值