第2章 Python序列
2.1 列表 []
2.1.1 列表创建与删除
list_a = []
list_b = ['a',2,'sirng']
可以利用 range 来创建list.
range函数
range([start,] stop [,step])
参数1 : 起点(默认0)
参数2 :终点
参数3 : 步长
删除列表,使用del + list
2.1.2 列表元素的增加
1)用"+"增加元素
>>> aList = [3,4,5]
>>> aList = aList + [6]
>>> aList
[3, 4, 5, 6]
2)append()方法
原地修改:内存地址不变,内存单元增加
>>> aList.append(9)
>>> aList
[3, 4, 5, 6, 9]
比较两个方法
import time
# 使用+方法,增加list 成员
result = []
start = time.time()
for i in range(10000):
result = result + [i]
print(len(result), ',', time.time() - start)
# 使用append方法,增加list成员
result = []
start = time.time()
for i in range(10000):
result.append(i)
print(len(result), ',', time.time() - start)
append更快,因为是直接原地增加元素,而不是更改指针指向。
基于内存的管理方式
对于list而言,list中包含的元素值的引用,而不是直接包含元素本身。
- 若直接修改序列变量的值,则地址改变
- 若通过下标修改,地址不变,元素地址改变。
a = [1,2,4]
b = [1,2,3]
a == b
False
a.append(4)
id (a) # 不变
a.remove(4)
id(a) # 不变
3)extend()方法
将另一个迭代对象的所有元素添加至该列表对象尾部。
不改变内存首地址,属于原地操作。
>>> a = [5,2,3]
>>> id(a)
1862358752576
>>> a.extend([7,8,9])
>>> id(a)
1862358752576
4)insert()方法
在列表的任意位置插入元素,但由于列表的自动内存管理功能,该方法会涉及到插入位置之后元素的移动,会影响处理速度。
尽量避免在列表中间插入和删除元素,建议优先使用append()和pop()方法
比较append()和insert处理速度的差别:
import time
# 测试:insert插入第一位和append插入最后一位的时间差
# 使用+方法,增加list 成员
def Insert():
a = []
for i in range(10000):
a.insert(0, i)
print(a)
def Append():
a = []
for i in range(10000):
a.append(i)
start = time.time()
# 做十次
for i in range(10):
Insert()
print('Insert:', time.time() - start)
start = time.time()
for i in range(10):
Append()
print('Append:', time.time() - start)
# Insert: 0.370502233505249
# Append: 0.010970830917358398
5)用乘法扩展列表对象(适用:list , string, tuple)
将列表整数相乘,生成一个新列表(地址变化),新列表是原列表的重复。
>>> a = [3,4,5]
>>> b = a
>>> id(a)
2699380239104
>>> a = a * 3 # 注意 a = a * 3时,地址改变;而a * 3时地址不变化
>>> a
[3, 4, 5, 3, 4, 5, 3, 4, 5]
>>> b
[3, 4, 5]
>>> id(a)
2697266430784 #地址改变,创建新列表
>>> id(b)
2699380239104
使用*
运算符,创建元素的引用,当修改某一个值的时候,也会被修改。
Tricky Part
# 先构成list: [None,None],再把list作为最外层list的元素,重复三次。
x = [[None] * 2] * 3
print(x)
# x[0][0]修改的是[[None, None], [None, None], [None, None]]中,第一个元素的第一个元素。
# 而该list是又*创建的,因此三个全是对于[None,None]的引用,更改任何一个中的一个元素,其他三个元素均会被修改。
x[0][0] = 5
print(x)
# 原理同上
x = [[1, 2, 3]] * 3
x[0][0] = 10
print(x)
2.1.3 列表元素的删除
1)del命令
- 可以删除一整个列表
- 可以删除指定位置上的元素(默认删除最后一个元素)
>>> a = [1,2,3]
>>> del a[2]
>>> a
[1, 2]
>>> del a
>>> a
Traceback (most recent call last):
File "<pyshell#73>", line 1, in <module>
a
NameError: name 'a' is not defined
2)pop()方法
删除元素并返回指定(默认为最后一个)位置上的元素。下标越界,则抛出异常。
>>> a = [1,2,3,4,5]
# 默认最后
>>> a.pop()
5
>>> a
[1, 2, 3, 4]
# 指定下标
>>> a.pop(2)
3
3)remove()方法
删除首次出现的指定元素,若不存在,抛出异常。
>>> a = [3,3,5,2,3,7,11]
>>> a.remove(3)
>>> a
[3, 5, 2, 3, 7, 11]
remove 的tricky
# 样例数组中不含有连续的1
def remove_1():
x = [1, 2, 1, 2, 1, 2, 1, 2, 1]
for i in x:
if i == 1:
x.remove(i)
print(x)
# 样例数组中含有连续的1
def remove_2():
x = [1, 2, 1, 1, 1, 2, 1, 1]
for i in x:
if i == 1:
x.remove(i)
print(x)
if __name__ == "__main__":
remove_1()
# [2, 2, 2, 2]
remove_2()
# [2, 2, 1, 1]
'''1删除不干净的原因是:Python会自动对列表内存进行收缩并移动列表元素,以保证所以元素之间没有空隙。
增加列表元素的时候也会移动。
当读到一个数组中有连续的1的时候,删除前一个1后,下一个1会收缩,向前移。导致下一个1没有被判断到。'''
优化
# 利用切片修正
der remove_c():
x = [1, 2, 1, 1, 1, 2, 1, 1]
for i in x[::]:
if i == 1:
x.remove(i)