Python list列表常用方法及其底层实现

添加元素

append()
方法用于在列表的末尾追加元素

list_test = ['2','a','b']
#追加元素
list_test.append(1)
print(list_test)

#整个元素被当作一个元素
list_test.append(('e',))
print(list_test)

结果
['2', 'a', 'b', 1]
['2', 'a', 'b', 1, ('e',)]

当给 append() 方法传递列表或者元组时,此方法会将它们视为一个整体,作为一个元素添加到列表中,从而形成包含列表和元组的新列表。

extend()
extend() 和 append() 的不同之处在于:extend() 不会把列表或者元祖视为一个整体,而是把它们包含的元素逐个添加到列表中。

list_test = ['2','a','b']
#追加元素
list_test.extend('1')
print(list_test)

#整个元素被当作一个元素
list_test.extend(('e',))
print(list_test)

结果
['2', 'a', 'b', '1']
['2', 'a', 'b', '1', 'e']

这里需要注意的时extend相当于一个迭代器一样把数据逐个添加到指定列表中

insert()
append() 和 extend() 方法只能在列表末尾插入元素,如果希望在列表中间某个位置插入元素,那么可以使用 insert() 方法。

list_test = ['2','a','b']
#追加元素
list_test.insert(0,'1')
print(list_test)

list_test.insert(1,('e',))
print(list_test)

结果
['1', '2', 'a', 'b']
['1', ('e',), '2', 'a', 'b']

删除元素

del

del 是 Python 中的关键字,专门用来执行删除操作,它不仅可以删除整个列表,还可以删除列表中的某些元素

list_test = ['2','a','b']
#根据索引
del list_test[0]
print(list_test)

#删除连续的一段
del list_test[::-1]
print(list_test)

结果
['a', 'b']
[]

pop()
根据索引值删除元素

list_test = ['2','a','b']
list_test.pop(0)
print(list_test)

#不指定索引
list_test.pop()
print(list_test)

结果
['a', 'b']
[]

remove()
根据元素值进行删除
除了 del 关键字,Python 还提供了 remove() 方法,该方法会根据元素本身的值来进行删除操作。

需要注意的是,remove() 方法只会删除第一个和指定值相同的元素,而且必须保证该元素是存在的,否则会引发 ValueError 错误。

list_test = ['2','a','b']
list_test.remove('a')
print(list_test)

#不指定索引
list_test.remove('c')
print(list_test)

结果
['2', 'b']
ValueError: list.remove(x): x not in list

clear()
删除列表所有元素
Python clear() 用来删除列表的所有元素,也即清空列表

list_test = ['2','a','b']
list_test.clear()
print(list_test)

结果
[]

修改元素

修改单个元素,直接对元素赋值即可

修改单个元素

list_test = ['2','a','b']
list_test[0]='1'
print(list_test)

结果
['1', 'a', 'b']

修改一组元素
Python 支持通过切片语法给一组元素赋值。在进行这种操作时,如果不指定步长,Python 就不要求新赋值的元素个数与原来的元素个数相同;这意味,该操作既可以为列表添加元素,也可以为列表删除元素。

list_test = ['2','a','b','v']
list_test[0:2]=['c','d','e']
print(list_test)

结果
['c', 'd', 'e', 'b', 'v']

查找元素

**index() **
index() 方法会返回元素所在列表中的索引值。
index() 方法用来查找某个元素在列表中出现的位置(也就是索引),如果该元素不存在,则会导致 ValueError 错误,所以在查找之前最好使用 count() 方法判断一下。

list_test = ['2','a','b']
print(list_test.index('a'))
print(list_test.index('a',0,2))

结果
1
1

count()
count() 方法用来统计某个元素在列表中出现的次数

list_test = ['2','a','b']
print(list_test.count('a'))

结果
1

列表的底层实现简述

具体结构如下

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;
    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size
     *     ob_item == NULL implies ob_size == allocated == 0
     * list.sort() temporarily sets allocated to -1 to detect mutations.
     *
     * Items must normally not be NULL, except during construction when
     * the list is not yet visible outside the function that builds it.
     */
    Py_ssize_t allocated;
} PyListObject;

列表本质上是一个长度可变的连续数组。其中ob_item是一个指针列表,里面的每一个指针都指向列表中的元素,而allocated则用于存储该列表目前已经被分配空间的大小

需要注意的是,allocated和列表的实际空间大小不同,列表实际空间大小,指的是len(list)返回的结果,也就是上面代码中注释的ob_size,表示该列表总共存储了多少元素。而在实际情况中,为了优化存储结构,避免每次增加元素都要重新分配内存,列表预分配的空间allocated往往会大于ob_size

因此 allocated 和 ob_size 的关系是:allocated >= len(list) = ob_size >= 0。

如果当前列表分配的空间已满(即 allocated == len(list)),则会向系统请求更大的内存空间,并把原来的元素全部拷贝过去。

上一篇:Python的垃圾回收机制(引用计数)


下一篇:Vue.set源码