Python中的列表(list)是最常用的数据结构之一,它提供了丰富的操作方法。让我们通过实际代码示例来深入理解这些基础但重要的操作。
python复制x = list(range(9))
del x[:2]
print(x) # 输出: [2, 3, 4, 5, 6, 7, 8]
这段代码展示了列表的创建和切片删除操作。range(9)生成0到8的序列,list()将其转换为列表。del x[:2]删除列表中前两个元素(索引0和1)。值得注意的是,切片操作遵循"左闭右开"原则,[:2]表示从开始到索引2(不包括2)的所有元素。
提示:
del语句不仅可以删除切片,还可以删除整个列表或指定索引的元素。与remove()方法不同,del是按索引操作而非按值操作。
python复制print(len(range(1,10))) # 输出: 9
这里展示了range对象的长度计算。range(1,10)生成从1到9的序列(不包括10),共9个元素。虽然range对象本身不是列表,但len()函数可以计算其长度。在Python 3中,range返回的是一个可迭代对象,而非实际的列表,这使其在处理大范围时更节省内存。
python复制print([1,2,3] * 3) # 输出: [1, 2, 3, 1, 2, 3, 1, 2, 3]
列表乘法操作符*可以将列表重复指定次数。这个操作创建的是原列表元素的浅拷贝,对于包含可变对象的列表需要特别注意:
python复制a = [[1,2]] * 3
a[0][0] = 5 # 所有子列表的第一个元素都会被修改
print(a) # 输出: [[5, 2], [5, 2], [5, 2]]
python复制aList = [3,4,5,6,7,9,11,13,15,17]
print(aList[3:7]) # 输出: [6, 7, 9, 11]
切片操作[start:end]获取从start到end-1的元素。切片还支持第三个参数step:
python复制print(aList[::2]) # 输出: [3, 5, 7, 11, 15] - 每隔一个元素取一个
print(aList[::-1]) # 输出: [17, 15, 13, 11, 9, 7, 6, 5, 4, 3] - 反转列表
python复制x=[3,7,5]
x=x.sort(reverse=True)
print(x) # 输出: None
这里有一个常见陷阱:sort()方法会就地排序列表并返回None。正确做法应该是:
python复制x=[3,7,5]
x.sort(reverse=True) # 直接修改x
print(x) # 输出: [7, 5, 3]
或者使用sorted()函数,它会返回新列表:
python复制x=[3,7,5]
x=sorted(x, reverse=True)
print(x) # 输出: [7, 5, 3]
python复制txt=["a","b","c","d","e"]
stop_words=["d","i"]
t=[x for x in txt if x not in stop_words]
print(t) # 输出: ['a', 'b', 'c', 'e']
列表推导式提供了一种简洁的方式来创建和过滤列表。上述代码相当于:
python复制t = []
for x in txt:
if x not in stop_words:
t.append(x)
列表推导式通常效率更高,代码更简洁。对于更复杂的条件,可以使用多个if:
python复制numbers = [1, 2, 3, 4, 5]
even_squares = [x**2 for x in numbers if x % 2 == 0]
python复制ls=["abcd","ab","cd","cdab"]
n,m=0,0
for line in ls:
if "ab" and "cd" in line:
n+=1
m+=1
elif "ab" in line:
n+=1
elif "cd" in line:
m+=1
print(n,m) # 输出: 3 3
这段代码有一个逻辑问题:条件"ab" and "cd" in line实际上等同于("ab") and ("cd" in line),因为非空字符串"ab"总是为True。正确的写法应该是:
python复制if "ab" in line and "cd" in line:
注意:Python中的
and优先级低于in,这种隐式优先级常常导致逻辑错误。建议使用括号明确表达意图。
python复制ls=[11,22,33,44]
for i in ls:
if i=="33":
print("找到!i=",i)
break
else:
print("未找到...")
for-else结构是Python中不太为人知但很有用的特性。else块会在循环正常完成(即没有遇到break)时执行。在这个例子中,因为33是数字而非字符串,条件i=="33"永远不会为真,所以会执行else块。
python复制k=0
for i in range(4):
for j in range(i+1):
k+=j
if j>1:
break
print(k) # 输出: 4
这段代码展示了嵌套循环和break的行为。外层循环i从0到3,内层循环j从0到i。当j>1时,内层循环会break,但外层循环继续。break只影响当前所在的循环层级。
计算过程:
最终输出为4,说明在i=3的循环中,k的增量没有被计入最终结果,因为print在循环结束后执行。
在处理大型列表时,不同的操作方式性能差异很大。例如:
+)会创建新列表,而extend()方法则直接修改原列表insert(0, x))比在末尾追加(append(x))慢得多x in list)对于大列表很慢,考虑使用集合(set)python复制# 不推荐
big_list = []
for i in range(100000):
big_list = big_list + [i]
# 推荐
big_list = []
for i in range(100000):
big_list.append(i)
python复制a = [[0]] * 3
a[0][0] = 1 # 所有子列表都会被修改
python复制lst = [1, 2, 3, 4]
for item in lst:
if item % 2 == 0:
lst.remove(item) # 可能导致意外行为
sort()和sorted():python复制a = [3, 1, 2]
b = a.sort() # b是None,a被排序
c = sorted(a) # c是新排序列表,a不变
python复制def func(a=[]): # 默认参数在函数定义时计算一次
a.append(1)
return a
func() # 返回 [1]
func() # 返回 [1, 1] 可能不是预期行为
掌握这些Python列表的基础和进阶操作,能够帮助开发者编写更高效、更可靠的代码。理解每个操作背后的原理和潜在陷阱,是成为Python高手的关键一步。