序列操作 - 补充

切片

# 如果把切片放在赋值语句的左边,或把他作为del操作的对象,
# 我们就可以对序列进行嫁接、切除或就地修改操作

l = list(range(10))

l[2:5] = [20,30] # [0, 1, 20, 30, 5, 6, 7, 8, 9]

del l[5:7] # [0, 1, 20, 30, 5, 8, 9]

l[3::2] = [11,22] # [0, 1, 20, 11, 5, 22, 9]

# l[2:5] = 100 # TypeError: can only assign an iterable 必须是可迭代对象

l[2:5] = [100] # [0, 1, 100, 22, 9]

print(l)

 序列的* 和 +

# 对序列使用+和* 不修改原有的操作,构建一个全新的序列

lis = [[1,2,3],4]
my_list = lis * 3 # 列表中包含的列表其实是三个引用,都指向同一个列表
my_list[0].append(12345)
print(my_list) # [[1, 2, 3, 12345], 4, [1, 2, 3, 12345], 4, [1, 2, 3, 12345], 4]


#建立由列表组成的列表
board = [['_'] * 3 for i in range(3)] # [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
board[1][2] = 'X'

# Error:不能追加同一个对象多次
# row = ['_'] * 3
# board = []
# for i in range(3):
#     board.append(row)

# 正确的: 每次迭代都新建了一个列表,作为新的一行追加到数组中
board = []
for i in range(3):
    row = ['_'] * 3
    board.append(row)
print(board)

序列中的增量赋值 (以+=举例子)

# 序列的增量赋值 以 ' += ' 举例子
'''
+= 背后的特殊方法是__iadd__ ,没有这个,就会调用 __add__

如果a实现了__iadd__方法,就会调用这个方法,同时对可变序列来说,a就会就地改动

如果没有实现的话,a+=b 相当于 a=a+b ,即首先计算a+b,在得到一个新的对象赋值给a。

'''
# 例子:
# 可变序列
l = [1,2,3]
print(id(l)) 
l *= 2
print(id(l)) # 同上 新的元素追加到列表上

# 不可变序列
t = (1,2,3)
print(id(t))
t *= 2
print(id(t)) # 跟上面的不一样 新的元组被创建

'''
对不可变序列进行重复拼接操作的话,效率会很低,
因为每次都有一个新对象,
而解释器需要把原来对象中的元素先复制给新的对象中,然后在追加新的元素

注意:
str是一个例外,CPython对其做了优化。
为str初始化内存的时候,程序会为它留出额外的可扩展空间
因此进行增量操作的时候,并不会涉及赋值原有字符串到新的位置这类操作

'''
t = (1,2,[30,40])
# t[2] = t[2] + [50,60] # 在赋值上出现的异常 元组不可变

t[2] += [50,60] # 写成 t[2].extend([50,60])就能避免异常
# 结果 1:t 变成 (1, 2, [30, 40, 50, 60])
# 结果 2:抛出异常:TypeError: 'tuple' object does not support item assignment

# 教训:1、不要把可变对象放在元组里面 2、增量赋值不是一个原子操作  3、了解背后的运行机制很有帮助

序列排序

# 序列 - 排序 list.sort方法和内置函数sorted
'''
list.sort方法会就地排序列表,也就是说不会把原列表复制一份。
这也是这个方法返回值为None的原因,不会新建一个列表,并未产生一个新对象

random.shuffle(随机排序)函数也遵守了返回值为None这个惯例

内置函数sorted,会新建一个列表作为返回值,
这个方法可以接收任何形式的可迭代对象作为参数,甚至包括不可变序列或生成器
不管sorted接收是怎样的参数,最后都会返回一个列表。

可选的关键字参数:
1、reverse
    True - 降序 默认值为False
    
2、key
    一个只有一个参数的函数,排序算法依赖的关键字
    默认用元素自己的值排序
    可以在内置函数min()和max()中起作用
'''
# 例子
fruits = ['grape','raspberry','apple','banana']
print(sorted(fruits)) # 新建一个列表作为返回值
print(fruits) # 原列表没有变化
print(sorted(fruits,reverse=True))
print(sorted(fruits,key=len)) # apple grape长度一样,相对位置没有变化
print(sorted(fruits,key=len,reverse=True))  # 算法稳定,apple grape长度一样,相对位置没有变化

print(fruits.sort()) # None
print(fruits) # 就地排序列表

切片顾头不顾尾的原因:

切片和区间会忽略最后一个元素的原因:顾头不顾尾的原因
    1、当只有最有一个位置信息时,我们也可以快速看出切片和区间里有几个元素
    2、当起止位置都可见时,可以快速计算出切片和区间的长度,用后一个数减去第一个下标即可。
    3、这样做也让我们可以利用任意一个下标来把序列分割成不重叠的两部分。

猜你喜欢

转载自www.cnblogs.com/liangying666/p/9550283.html