Python运算符及表达式(包含切片)
Python——运算符及表达式(包含切片)
基本介绍
运算符是一些特殊的符号,主要用于数学计算、比较大小和逻辑运算等,由于Python具有多态性,于是即使是同一个运算符,对应不同类型的对象起到的效果是大不相同的
表达式是使用运算符将不同类型的数据按照一定的规则连接起来的式子,单个常量或变量也可以看作最简单的表达式
Python不支持++和 - -运算符,虽然有些地方在形式上是相同的,但是意义完全不同,比如,3++1 和 3–1 实际表示为 3+1 和 3-(-1),结果均为 4
运算符的优先级和结合性
优先级:当多个具有不同优先级的运算符同时出现在一个表达式中时,先执行哪个运算符
结合性:当多个具有相同优先级的运算符(相同运算符也是自己的同优先级运算符)同时出现在一个表达式中时,先执行哪个运算符
对于一个表达式先比较优先级,如果优先级相同,再比较结合性,由此确定该表达式中各个运算符的运算次序
在我们非常清楚Python运算优先级的前提下,最好运算符的书写的时候,还是要以圆括号来标记优先级,这样可读性强,也是一个良好的编程习惯
运算符名称 | Python运算符 | 优先级 | 结合性 |
---|---|---|---|
字符串转换 | ‘expression,…’ | 27 | ----- |
字典显示 | {key:value,…} | 26 | ----- |
列表显示 | [expressions…] | 25 | ----- |
绑定或元组显示 | (expressions…) | 24 | ----- |
函数调用 | x(arguments…) | 23 | ----- |
await 表达式 | x[index:index] | 22 | ----- |
下标 | x[index] | 21 | 左 |
属性引用 | x.attribute | 20 | 左 |
乘方 | await x | 19 | 右 |
乘方 | ** | 18 | 右 |
按位非 | ~x | 17 | 右 |
正负号 | +x,-x | 16 | 右 |
乘法、除法与取余 | *,/,//,% | 15 | 左 |
加法与减法 | +,- | 14 | 左 |
移位 | <<,>> | 13 | 左 |
按位与 | & | 12 | 右 |
按位异或 | ^ | 11 | 左 |
按位或 | | | 10 | 左 |
比较 | <,<=,>,>=,!=,== | 9 | 左 |
同一性测试 | is,is not | 8 | 左 |
成员测试 | in,not in | 7 | 左 |
布尔“非” | not x | 6 | 右 |
布尔“与” | and | 5 | 左 |
布尔“或” | or | 4 | 左 |
条件表达式 | if – else | 3 | 左 |
lambda 表达式 | lambda | 2 | ----- |
赋值运算符、复合赋值运算符 | =、+=、-=、 *= 、/=、//=、%= | 1 | 右 |
具体运算符讲解
1.赋值运算符
作用
从Python为动态类型语言的特点可知,赋值的过程中会自动根据左值对象的类型改变右值对象类型
赋值的本质为右值对象给予左值对象其自身具有的对象id的过程
特点
支持解包赋值,需要赋值符左端的操作数数目与右端序列对象中元素数目必须相同,复合赋值符不支持解包赋值
所谓 a, b = b, a 形式的解包赋值(多个对象赋值多个对象)其实是将左端的操作数全部看作一个元组的元素而已,本质为两个序列元素的一对一的赋值
在Python中下面这种写法是依旧为一个正常的写法
y = 1
x = 1
a = y = x
但是下面这种写法在Python中是会抛出异常的,具有语法错误
y = 1
x = 1
a = (y = x)
而在C语言中,类似这样的赋值运算符的左操作数为一个赋值表达式的情况是不会报错的,而是可以按照我们的预想,以赋值表达式中的赋值数据即为一整个赋值表达式的运算结果,然后再进行一次赋值运算
案例
a,b,c = [1,2,3] #实际为将左端的操作数全部看作一个元组的元素
print(a,b,c)
#输出结果:1 2 3
[a,b,c] = [1,2,3]
print(a,b,c)
#输出结果:1 2 3
a,b,c = {1:2,2:3,3:4} #对于字典直接进行解包,默认是对键进行解包
print(a,b,c)
#输出结果:1 2 3
a = 0
b = 1
a,b = b,a #通过两个元组元素的相互赋值,可以实现两个变量数值的交换
print(a,b)
#输出结果:1 0
a = 0
b = 1
(a,b) = (b,a)
print(a,b)
#输出结果:1 0
lst = [[1],[2],[3]]
a,b,c = lst #赋值的过程为一个lst给予a,b,c自身具有的对象id的过程
a.append(4)
b[0] = 0
print(lst)
#输出结果:[[1, 4], [0], [3]]
2.复合赋值运算符
作用
先进行左值和右值的算术运算,再把运算结果赋值给左值,简化了表达式形式
特点
复合赋值符不支持解包赋值
相对于将复合赋值运算符拆开成一个运算符和一个赋值符进行计算来说,复合赋值符对于可变序列为原地操作,可变序列的id不变,不会生成新的可变序列对象,对于不可变序列依旧会生成新对象,因为原序列的元素id皆不可变
其实复合赋值运算符的工作原理,就是将"a += 1"转化为"a = a + 1",即会先去访问a存储的id所对应的对象,再进行加法运算和普通赋值的操作
佐证:(如果看不太懂,可以移步 Python——面向对象 )
class Class():
num = 10
@staticmethod
def printf():
print("类属性", Class.num)
instan = Class()
instan.num+=1
instan.printf()
print("实例属性", instan.num)
#输出结果:
"""
类属性 10
实例属性 11
"""
基础知识:实例对象只能对实例属性进行创建和修改,可以对类属性进行访问,而不能对类属性进行创建和修改
代码解析:代码"instan.num+=1"的实际上为"instan.num = instan.num + 1",即实例对象先访问了类属性num,然后将类属性值10加1,得到了11,进行赋值的时候,由于实例对象不能对类属性进行创建和修改,于是实际上是创建了一个新的实例属性num,值为11。于是最后的打印结果中,实例属性num值为11,而类属性num值依旧为10
案例
lst = [1,2,3]
print('原始列表的内容以及id:',lst,id(lst))
lst += [4,5,6]
print('使用复合赋值符以后列表的内容以及id:',lst,id(lst))
#输出结果:
"""
原始列表的内容以及id: [1, 2, 3] 2447912307520
使用复合赋值符以后列表的内容以及id: [1, 2, 3, 4, 5, 6] 2447912307520
"""
lst = [1,2,3]
print('原始列表的内容以及id:',lst,id(lst))
lst = lst + [4,5,6]
print('使用一个运算符和一个赋值符进行运算以后列表的内容以及id:',lst,id(lst))
#输出结果:
"""
原始列表的内容以及id: [1, 2, 3] 2268763031808
使用一个运算符和一个赋值符进行运算以后列表的内容以及id: [1, 2, 3, 4, 5, 6] 2268763117184
"""
st = {1,2,3}
print('原始集合的内容以及id:',st,id(st))
st |= {4,5,6}
print('使用复合赋值符以后集合的内容以及id:',st,id(st))
#输出结果:
"""
原始集合的内容以及id: {1, 2, 3} 2140729822336
使用复合赋值符以后集合的内容以及id: {1, 2, 3, 4, 5, 6} 2140729822336
"""
dct = {1:2,2:4,3:4}
print('原始字典的内容以及id:',dct,id(dct))
dct |= {4:5,5:6,6:7}
print('使用复合赋值符以后字典的内容以及id:',dct,id(dct))
#输出结果:
"""
原始字典的内容以及id: {1: 2, 2: 4, 3: 4} 2191737847040
使用复合赋值符以后字典的内容以及id: {1: 2, 2: 4, 3: 4, 4: 5, 5: 6, 6: 7} 2191737847040
"""
tpl = (1,2,3)
print('原始元组的内容以及id:',tpl,id(tpl))
tpl += (4,5,6)
print('使用复合赋值符以后元组的内容以及id:',tpl,id(tpl))
#输出结果: #对于不可变序列的id即使使用复合赋值符依旧会发生改变,会创建新对象
"""
原始元组的内容以及id: (1, 2, 3) 1598146332736
使用复合赋值符以后元组的内容以及id: (1, 2, 3, 4, 5, 6) 1598146623232
"""
3.算术运算符(四则运算)
作用
进行数学上的各种数值计算
特点
算术转化(针对于四则运算、取余/模、乘方):
如果任一参数为复数,另一参数会被转换为复数
如果任一参数为浮点数,另一参数会被转换为浮点数
如果两者都为整数,不需要进行转换
- 加法运算符
- 对象为数字类型(int、float、complex)
- 效果为两个数相加
- 对象为列表,元组,字符串类型
- 效果为进行同类型序列元素的合并,形成一个新的序列对象(结果序列的id和进行合并的序列id皆不同)
- 对象为数字类型(int、float、complex)
- 减法运算符
- 对象为数字类型(int、float、complex)
- 效果为两个数相减
- 对象为集合类型
- 效果为集合取差集
- 对象为数字类型(int、float、complex)
- 乘法运算符
- 对象为数字类型(int、float、complex)
- 效果为两个数相乘
- 对象为列表,元组,字符串类型
- 效果为实现序列中元素的重复,形成一个新的序列对象(结果序列的id和进行相乘的序列id皆不同,本质为元素id的复制,为浅拷贝),特别地,如果乘以 0 或者 负数 ,会导致序列清空
- 对象为数字类型(int、float、complex)
- 除法运算符
- 真除法运算符 “/”
- 对象为数字类型(int、float、complex)
- int 类型对象相除会输出一个 float 类型对象
- 对象为数字类型(int、float、complex)
- 整除(地板除)法运算符 “//”
- 对象为数字类型(int、float、complex)
- int 类型对象相整除的结果仍是 int 类型对象,整除的结果就是使用 ‘floor’ 函数进行算术除法的结果。 除以零的运算将抛出异常
- 对象为数字类型(int、float、complex)
- 真除法运算符 “/”
案例
lst1 = [1,2,3]
lst2 = [4,5]
lst3 = lst1 + lst2
print('作为加法运算符操作数的两个列表对象id:',id(lst1),id(lst2))
print('新列表对象id:',id(lst3))
#输出结果:
"""
作为加法运算符操作数的两个列表对象id: 2729060964608 2729060433216
新列表对象id: 2729061050112
"""
st1 = {1,2,3,4,5}
st2 = {4,5}
st3 = st1 - st2
print(st3)
#输出结果:{1, 2, 3}
lst1 = [[1]]
print('原列表可变元素的id:',id(lst1[0]))
lst2 = lst1*3
print('新列表可变元素的id:',id(lst2[0]),id(lst2[1]),id(lst2[2]))
lst2[0].append(2)
print('对新列表的一个元素进行修改以后的新列表内容:',lst2)
#输出结果:
"""
原列表可变元素的id: 2095214205760
新列表可变元素的id: 2095214205760 2095214205760 2095214205760
对新列表的一个元素进行修改以后的新列表内容: [[1, 2], [1, 2], [1, 2]]
"""
lst1 = [1,2,3]
lst2 = lst1*0
print(lst2)
#输出结果:[]
lst1 = [1,2,3]
lst2 = lst1*-1
print(lst2)
#输出结果:[]
data = 2/1
print(data)
#输出结果:2.0
data = 1/0
print(data)
#抛出异常:ZeroDivisionError: division by zero
data1 = int(6/-4)
data2 = 6//-4
print('使用先真除,再取整的方法:',data1)
print('使用整除的方法:',data2)
#输出结果:
"""
使用先真除,再取整的方法: -1
使用整除的方法: -2
"""
4.算术运算符(取余/模、乘方)
作用
进行数学上的各种数值计算
特点
- 算术转化(针对于四则运算、取余/模、乘方):
- 如果任一参数为复数,另一参数会被转换为复数
- 如果任一参数为浮点数,另一参数会被转换为浮点数
- 如果两者都为整数,不需要进行转换
- 取余/模运算符
- 对象为数字类型(int、float、complex)
- 效果为前一个数对后一个进行取余,可以对实数进行取余,但是要注意精度问题。整除与模运算符的联系可通过该等式说明: x == (x//y)*y + (x%y),此即为模的数学定义
- 对象为数字类型(int、float、complex)
- 乘方运算符
- 对象为数字类型(int、float、complex)
- 效果为前一个数以后一个数为指数进行乘方,对于 int 类型的操作数,结果将具有与操作数相同的类型,除非第二个参数为负数(在这种情况下,所有参数会被转换为 float 类型并输出 float 类型的结果)。对负数进行分数幂次运算将返回 complex 类型对象。对 0.0 或者 0 进行负数幂次运算将抛出异常
- 对象为数字类型(int、float、complex)
案例
data = 10%-3
print(data) #data = 10 -(10//-3)* -3 = 10 - -4 * -3 = 10 - 12 = -2
#输出结果:-2
data = 6%3.6
print(data)
#输出结果:2.4
data = 2**3
print(data)
#输出结果:8
data = 8**(1/3)
print(data)
#输出结果:2.0
data = 2**-1
print(data)
#输出结果:0.5
data = (-9)**0.5
print(data)
#输出结果:(1.8369701987210297e-16+3j)
data = 0**-1
print(data)
#引发异常:ZeroDivisionError: 0.0 cannot be raised to a negative power
5.逻辑运算符
作用
实现逻辑运算 —— 与 或 非
特点
- 短路算法(针对于双操作数的 逻辑与 和 逻辑或):
- 仅仅只对必须要计算的表达式进行计算,目的是要将计算机的工作最小化
- 利用短路算法,我们可以通过预测不同情况发生的概率,调整顺序,提高代码的运行效率
- 有意思的是,不同与为编译型语言的C语言,在作为解释型语言的Python的短路算法中,即使被短路掉的语句的语法有问题,也不会抛出异常(作为编译型语言的C语言在这种情况下会报错),因为解释型语言对语句进行逐个编译,如果某一个语句不会被执行到,那么该语句就不会被解释器所检查,自然语法问题也不会暴露出来
- 逻辑与
- 以exp1 and exp2为例,如果exp1的值等价于False则返回exp1的值,否则返回exp2的值
- 逻辑或
- 以exp1 or exp2为例,如果exp1的值等价于True则返回exp1的值,否则返回exp2的值
- 逻辑非
- 返回的一定是一个布尔类型对象 True 或者 False
案例
data = 1 or 2
print(data)
#输出结果:1
data = 0 and 1
print(data)
#输出结果:0
data = 0 and amazing() #由于短路算法,于是即使函数amazing未定义,也不会抛出异常
print(data)
#输出结果:0
b = not 8
print(b)
#输出结果:False
6.关系运算符(数学中的比较、同一性测试、成员测试)
作用
进行数学上的各种数值比较,以及对两个对象是否是同一个对象的判断,一个对象是否作为了另一个对象的元素的判断
特点
连续使用多个的关系运算符的表达式会按传统算术法则来解读,相当于两个关系运算分别进行之后,最后再进行一个逻辑与运算(也满足逻辑运算的短路算法),使用数学形式进行表示就是:如果 a, b, c, …, y, z 为表达式同时 op1, op2, …, opN 为关系运算符,则 a op1 b op2 c … y opN z 就等价于 a op1 b and b op2 c and … y opN z,比如,表达式1 < 3 < 5 等价于 表达式1 < 3 and 3 < 5
计算结果必定为一个布尔类型对象 True 或者 False
- <、>、<=、>=、==、!=
- 对象为列表,元组,字符串类型
- 为序列中的每一个元素对应依次进行比较
- 对象为集合类型
- 比较的是数学中的两个集合的关系(即为子集和超集关系的检测),所以如果集合A>集合B返回False,不一定集合A<=集合B返回的就一定是True
- 对象为列表,元组,字符串类型
- is、is not
- 判断的是两个对象的 id 是否相同,要和用来判断两个对象的内容数值是否相同的比较运算符"==“区分开来,比如张三买的手机和李四买的手机,如果使用比较运算符”=="进行判断,结果为True,而如果使用同一性运算符"is"判断,结果为False
- in、not in
- 判断是否在右操作数中存在某一个元素的内容数值和左操作数的内容数值相同
- 对于列表、元组、字符串,时间复杂度为线性级的,而对于集合和字典,时间复杂度为常数级的,因为集合和字典内部为一个散列结构
- 对于字典来说,是将左操作数看作字典的键,判断字典中是否有相同的键存在
- 对于字符串来说,可以判断子串是否在右操作数(也是一个字符串类型对象)中
案例
b = 3 > 1 < 2
print(b)
#输出结果:True
b = 1 in [1,2] in [[1,2],3,4]
print(b)
#输出结果:True
b = 1 is not 2 is 2
print(b)
#输出结果:True
b = [1,2,4] > [1,2,3]
print(b)
#输出结果:True
b1 = {1,2}>{2,3}
b2 = {1,2}<{2,3}
b3 = {1,2}=={2,3}
print(b1,b2,b3)
#输出结果:False False False
b = 1,2,3 < 2,3,4
print(b) #以, 的形式构造元组,其优先级低于比较运算符
#输出结果:(1, 2, False, 3, 4)
lst1 = [1,2,3]
lst2 = [1,2,3]
b = lst1 is lst2
print('两个列表的内容数值是否相同',lst1 == lst2)
print('两个内容数值相同的列表id:',id(lst1),id(lst2))
print('两个列表的id是否相同:',b)
#输出结果:
"""
两个列表的内容数值是否相同 True
两个内容数值相同的列表id: 1627688110080 1627687583040
两个列表的id是否相同: False
"""
print(1 is True) #说明True和1是两个东西,虽然使用True进行四则运算的时候有时会转化为1
#输出结果:False
print(0 is False) #说明False和0是两个东西,虽然使用False进行四则运算的时候有时会转化为0
#输出结果:False
b = [1] in [1,2]
print(b)
#输出结果:False
b = [1] in [[1],2]
print(b)
#输出结果:True
b = 1 in {1:2,3:4}
print(b)
#输出结果:True
b = "abc" in "abcdef"
print(b)
#输出结果:True
b = "abc" in "abdefc"
print(b)
#输出结果:False
7.位运算符
作用
将操作数转化为二进制,进行二进制层面上的按位运算
特点
对于数字类型,只能作用于int类型对象,对应的运算结果为一个int类型对象
- 按位与&
- 对象为int类型
- 效果为两个二进制数按位与
- 对象为集合类型
- 效果为两个集合的交集
- 对象为int类型
- 按位或|
- 对象为int类型
- 效果为两个二进制数按位或
- 对象为集合类型
- 效果为两个集合的并集
- 对象为int类型
- 按位异或^
- 对象为int类型
- 效果为两个二进制数按位异或
- 对象为集合类型
- 效果为两个集合的对称查集
- 对象为int类型
- 按位取反~
- 对象为int类型两个二进制数按位取反(连同符号位)
- 左移 <<
- 对象为int类型,高位溢出舍弃,低位补0,移动位数不可为负数。左移 n 位被定义为乘以 pow(2,n)
- 右移 >>
- 对象为int类型,低位溢出舍弃,高位补0,移动位数不可为负数。右移 n 位被定义为被 pow(2,n) 整除
案例
bit = 0b1010 & 0b1111
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#输出结果:
"""
十进制形式: 10
二进制形式: 0b1010
"""
st = {1,2,3}&{2,3,4}
print(st)
#输出结果:{2, 3}
bit = 0b1010 | 0b0000
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#输出结果:
"""
十进制形式: 10
二进制形式: 0b1010
"""
st = {1,2,3}|{2,3,4}
print(st)
#输出结果:{1, 2, 3, 4}
bit = 0b1010 ^ 0b1111
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#输出结果:
"""
十进制形式: 5
二进制形式: 0b101
"""
st = {1,2,3}^{2,3,4}
print(st)
#输出结果:{1, 4}
bit = ~4 #4的二进制补(原)码为00001000,-5的二进制补码为11110111
print(bit)
#输出结果:-5
bit = 0b1010 << 2
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#输出结果:
"""
十进制形式: 40
二进制形式: 0b101000
"""
bit = 0b1010 >> 2
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#输出结果:
"""
十进制形式: 2
二进制形式: 0b10
"""
bit = 0b1010 >> -1
print('十进制形式:',bit)
print('二进制形式:',bin(bit))
#引发异常:ValueError: negative shift count
一些特殊的表达式
1.条件表达式
格式
expr1 if condition else expr2
首先计算条件表达式condition,如果计算结果的布尔值为True,则执行表达式expr1并将计算结果作为整个条件表达式的计算结果,否则执行expr2并将计算结果作为整个条件表达式的计算结果
特点
支持短路算法
可以实现嵌套使用,但是一般不建议这么用
案例
data = 1 if 1+2 else amazing()
print(data)
#输出结果:1
data = 1 if 1 else 2 if 0 else 3
print(data)
#输出结果:1
2.lambda 表达式
格式
lambda [parameter_list] : expression
特点
lambda 表达式(有时称为 lambda 构型)是一个匿名函数,lambda 表达式会产生一个函数对象,可以将lambda函数作为其他函数的实际参数进行使用,通过 lambda 表达式创建的函数不能包含注释
此篇的重点在于运算符及表达式,更加详细的关于lambda 表达式构建出的匿名函数特点,见Python——函数
案例
Lambda = lambda a,b : a+b
data = Lambda(1,2)
print(data)
#输出结果:3
Lambda = lambda item : item**2
data = list(map(Lambda, range(5)))
print(data)
#输出结果:[0, 1, 4, 9, 16]
3.星号表达式
格式
* 标识符 、** 标识符 或者 * 序列
特点
- 对传入函数的多个实际参数进行打包,作为函数的形式参数,用于参数传递
- * 会将对应传入的多个位置参数打包为一个元组类型对象
- ** 会将对应传入的多个关键字参数打包为一个字典类型对象
- 对传入函数的一个可迭代对象进行解包,作为函数的实际参数,用于参数传递
- * 会在可迭代对象的每一个元素的相对位置保持不变的情况下,将可迭代对象的所有元素对应转化为多个位置参数(对于字典,仅仅取出键而已),再进行函数传参
- ** 会在字典的每一个键值对的相对位置保持不变的情况下,将字典的所有键值对对应转化为多个关键字参数,再进行函数传参,当然,这必须使字典的键符合为Python的标识符的要求,因为转化以后原先字典的键即为函数形参变量名(变量名就是一种标识符)
- 位于一个赋值表达式的左侧,用于打包,同时形成一个列表对象
- 只能使用*,星号表达式必须为列表或者元组中的元素,否则会抛出异常
- 位于一个赋值表达式的右侧,用于解包
- 只能使用*,星号表达式必须为列表或者元组中的元素,否则会抛出异常
案例
def test(a,*b,**c):
print(a,b,c)
test(1,2,3,d=4,e=5)
#输出结果:1 (2, 3) {'d': 4, 'e': 5}
def test(a,b,c):
print(a,b,c)
test(*[1,2,3])
#输出结果:1 2 3
def test(a,b,c):
print(a,b,c)
test(**{'a':1,'b':2,'c':3})
#输出结果:1 2 3
a,*b,c = [*[1,2,3],4,5]
print(a,b,c)
#输出结果:1 [2, 3, 4] 5
*a = range(5)
print(a)
#抛出异常:SyntaxError: starred assignment target must be in a list or tuple
*a, = range(5)
print(a)
#输出结果:[0, 1, 2, 3, 4]
4.yield 表达式
用于构造生成器,详见Python——生成器
用于Python多任务中
5.await 表达式
序列切片
格式
[start] : [stop] [ : [step] ]
切片就是在序列对象(字符串、元组或列表)以及range对象中选择某个范围内的项,其中的start、stop、step的含义和range函数中的同名形式参数的含义完全相同,且皆表示元素下标。下面表格中所指的a为一个具有10个元素序列对象
特点
- 切片产生的新对象与原对象类型相同,如果没有捕获到元素,会返回相应类型的空序列
- 切片可以支持双索引
- 可以使用超出实际可使用的下标的范围的值作为start、stop、step的值,不会抛出异常,所以使用切片能够提高代码的健壮性
- 切片可被用作表达式以及赋值或 del 语句的目标
- 使用序列可以实现列表元素的增添
- 关于step
- step应该分成正负号和==数值大小(绝对值)==两部分来分析
- step的正负号仅仅决定两个端点之间的元素的输出方向为从右到左还是从左到右,正号为左到右;负号为右到左
- step的数值大小(绝对值)仅仅决定输出步长
- 没有指定step,step默认为1,即默认为从左到右输出
- step应该分成正负号和==数值大小(绝对值)==两部分来分析
- 关于start和stop
- 没有指定start,start默认为0;没有指定stop,stop会依据start和step的值,并且以"尽可能多地捕获元素"作为目标来进行取值(没有指定stop时,stop比较灵活,难以说明,请读者自行测试)
- start和stop确定了两个端点(无论是使用正数索引,还是使用负数索引,都仅仅是确定了两个端点而言),其中start端点处的元素会输出,stop端点处的元素不会输出
- 确定输出方向时(即指定step的正负号),要先判断从start那端到stop那一端的方向,step的正负要与此方向进行匹配,否则切片结果为一个空序列
- 如果start和stop都未指定,则表示范围为一整个序列对象
案例
lst = [1, 2, 3, 4, 5]
s = lst[1:4]
print(s)
#输出结果:[2, 3, 4]
lst = [1, 2, 3, 4, 5]
s = lst[5:]
print(s)
#输出结果:[]
lst = [1, 2, 3, 4, 5]
s = lst[4:1]
print(s)
#输出结果:[]
lst = [1, 2, 3, 4, 5]
s = lst[-4:-1]
print(s)
#输出结果:[2, 3, 4]
lst = [1, 2, 3, 4, 5]
s = lst[1:1000]
print(s)
#输出结果:[2, 3, 4, 5]
lst = [2, 3, 4, 5] #将元素添加在原列表头部
lst[:0] = [1]
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [1, 2, 3, 4] #将元素添加在原列表尾部
lst[len(lst):] = [5]
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [6, 2, 7, 4, 8]
lst[::2] = [1, 3, 5]
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [6, 2, 7, 4, 8]
lst[::2] = [1, 3]
print(lst)
#引发异常:attempt to assign sequence of size 2 to extended slice of size 3
lst = [6, 2, 7, 4, 8]
lst[::2] = [1, 3, 5, 6]
print(lst)
#引发异常:attempt to assign sequence of size 4 to extended slice of size 3
lst = [1, 2, 4, 5]
lst[2:2] = [3]
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [1, 2, 6, 7, 3, 4, 5] #这种删除元素的方法仅仅适用于切片范围连续的情况下
lst[2:4:] = []
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [1, 2, 6, 3, 7, 4, 5]
lst[2:5:2] = []
print(lst)
#引发异常:attempt to assign sequence of size 0 to extended slice of size 2
lst = [1, 2, 6, 3, 7, 4, 5] #删除元素的通用方法
del lst[2:5:2]
print(lst)
#输出结果:[1, 2, 3, 4, 5]
lst = [1, 2, 3, 4, 5]
s = lst[:]
print(s)
#输出结果:[1, 2, 3, 4, 5]