负数下标不越界条件是:i 满足 -len(seq) ≤ i
索引访问时负数下标怎么算才不越界
python 序列(如
list、str、tuple)支持从 0 开始的正向索引,也支持从 -1 开始的反向索引。seq[-1]指最后一个元素,seq[-len(seq)]等价于seq[0]。越界判断很简单:只要i满足-len(seq) ,就不会报IndexError。常见错误是误以为
seq[-0]是倒数第一个——其实-0就是0,它取的是首元素。另外,对空序列[]做任何索引(包括[0]或[-1])都会直接抛出IndexError: list index out of range。切片
[start:end:step]的边界行为和默认值切片不会报索引错误,超出范围会自动截断。比如
[1,2,3][5:10]返回空列表[],"abc"[1:100]返回"bc"。默认值为:start=0(正向)、end=len(seq)、step=1;当step为负时(如[::-1]),start默认变成-1,end默认变成-(len(seq)+1),所以[::-1]才能完整反转。
[1,2,3,4][1:3]→[2,3](左闭右开,不含end)[1,2,3,4][1:10:2]→[2,4](超出end自动停)"hello"[::-2]→"olh"(从末尾开始,隔一个取一个)相加与相乘只允许同类型序列参与
+要求左右操作数类型一致:[1,2] + (3,4)报TypeError;"a" + ["b"]也不行。相乘是「重复拼接」,3 * [1,2]得[1,2,1,2,1,2],但[1,2] * 3.5会报错——右操作数必须是整数(int),浮点数或字符串都不行。立即学习“Python免费学习笔记(深入)”;
注意:
*=是就地操作,对可变序列(如list)会修改原对象;而+和*总是返回新对象。
in和not in成员检查的性能与陷阱
in对list/tuple是 O(n) 线性扫描,大数据量时很慢;对str是优化过的子串搜索(仍可能较慢);对set或dict键才是平均 O(1)。别在循环里反复写if x in my_list:,应提前转成set。容易忽略的点:
"" in "abc"返回True(空字符串是任意字符串的子串);None in [None, 1]没问题,但float("nan") in [float("nan")]是False,因为 NaN 不等于自身。成员检查不触发自定义
__eq__以外的逻辑,也不会调用__contains__以外的方法——除非类显式实现了它。
