Python中的列表不是由若干个独立的节点相互引用而成的,而是一整块单一连续的内存区块(相似于我们通常称之为数组(array)的储存结构)。这直接导致了它与链表之间的一些重要分别(访问很快,中间插入较慢)。今天,小编向大家介绍一下Python列表运用常见陷阱及如何避免。
C++的STL的list容器是一个双向链表(doubly-linked lists,数据元素处于不是连续的、没有关系的内存区域,面通过指针链接起来),可高效地进行插入删除元素。
Python的list提供随机访问(下标+偏移值操作),STL的list不提供随机访问,需要遍历操作。
1 列表对象与相同值(Python列表运用常见陷阱) 变量是对对象的引用,当值相同时,列表会创建两个对象,元组也一样,而字符串却只创建一个对象
t1 = [1,2,3]
t2 = [1,2,3]
print(id(t1))
print(id(t2))
print(id(t1[2]))
print(id(t2[2]),'\n')
output:
36450872
20379848
1429201712
1429201712
元组在这一方面与列表一样:
tp1 = (1,2,3)
tp2 = (1,2,3)
print(id(tp1))
print(id(tp2))
output:
19722888
36551816
字符串对于相同的值,会指向同一个对象:
s1 = 'abcde'
s2 = 'abcde'
print(id('abcde'))
print(id(s1))
print(id(s2),'\n')
output:
36525376
36525376
36525376
2 列表与别名(Python列表运用常见陷阱) 当两个变量相互赋值时,左值是右值的别名,对于可变对象而言,修改了任何其一,另一个也会如此,因为它们有相同的指向。
t1 = [4,5,6]
t2 = [4,5,6]
t3 = t2
# 修改前的内存指向见下图
t2[1] = 77
t3[2] = 88
# 修改后的内存指向见下图
print(t1)
print(t2)
print(t3)
output:
[4, 5, 6]
[4, 77, 88]
[4, 77, 88]
# 修改前的内存指向

Python列表运用常见陷阱图1 # 修改后的内存指向

Python列表运用常见陷阱图2 避免别名陷阱的方式是尽量不运用别名,而是通过复制列表来达到目的
如:
t = [3,2,1]
t2 = t[:]
t2.sort()
3 列表作为函数参数(Python列表运用常见陷阱) 列表作为可变对象在作为函数参数时,可以修改列表,当切片操作时例外.
1.1 修改操作时,函数内外的相同指向的变量会一同修改
def modilist(t):
....t[2] = 44
....t.append(99)
....t += [111]
....print(t)
t = [4,5,6]
modilist(t)
print(t)
output:
[4, 5, 44, 99,111]
[4, 5, 44, 99,111]
1.2 切片操作创建新列表时,原始列表并不改变
def striplist(t):
....t = t[1:len(t)-1]
....print(t)
t = [4,5,6,7,8]
striplist(t)
print(t)
output:
[5, 6, 7]
[4, 5, 6, 7, 8]
4 避免列表对象运用修改方式后的赋值操作(Python列表运用常见陷阱) 大部分列表方式都是修改参数并返回None的。这与字符串、元组等不可变对象的方式不一样,不可变对象的方式通常都会返回一个相同类型的不可变对象。
t = [3,2,8,5,4]
t = t.sort() # 一种无意义的写法
print(t) # output:None
有意义的写法应该是:
t = [3,2,8,5,4]
t.sort()
print(t) # output:[2, 3, 4, 5, 8]
5 当有不一样的方式可以做同样的事情时,选择统一风格(Python列表运用常见陷阱) 如从列表中删除一个元素,可以选择pop、remove、del或者切片赋值;
如添加一个元素可以选择append或+操作符。
t = [3,2,8,5,4]
t.append[11]
t += [22]
以下写法是错误的,或没有意义:
t.append([11])
t = t.append(x)
t += 11
t + [11]
今天小编就讲解到这,Python列表运用常见陷阱及如何避免你学会了吗?
|