记录一下涉及到字符串,列表,元组和字典这几个基本类型的常用操作吧。

字符串

字符串的本质是就是一些字符组成的不可变序列,Python把单个字符视作长度为1的字符串进行统一处理。使用字符串字面量来定义一个字符串对象

1
s = 'abcd'

索引

可以使用索引获取指定位置的字符:

  • 正向索引从第一个字符开始,依次为s[0],s[1]...
  • 反向索引从最后一个字符开始,依次为s[-1],s[-2]...
1
2
3
4
s = "abcd"

s[1] # "b"
s[-1] # "d"

超出实际范围的索引会报错。

字符串是不可变的,因此通过索引获得的只是可读的,不能进行修改

1
2
3
s = "abcd"

s[0]='a' # 报错

切片

可以使用切片获取字符串片段来创建新的字符串,切片的基础语法为str[lower:upper:step],lower代表切片的起点,upper代表终点(不含),step代表步长(省略时默认为1)

切片的具体语法非常灵活,这里只给出几个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
s = "abcdefg"

s[:]
# 切片整个字符串 "abcdefg"
a = s[:] # 复制得到新的字符串

s[:-3]
# 切片为 "abcd"

s[-3:]
# 切片为 "efg"

s[::2]
# 切片为 "aceg"

s[:100]
# 切片为 "abcdefg"

注意:超出实际范围的切片有时不会报错。

列表

列表就是一些对象组成的可变序列,可以使用列表字面量来定义一个列表对象

1
2
s = [1,2,3]
s = [] # 等价于 s = list()

列表对象可以是任何类型的,例如数值或字符串,还可以是列表自身等, 一个列表中的不同对象也可以是不同元素,例如

1
2
s1 = ['a',1]
s2 = [[1,2],'str']

使用len(s)可以获取列表长度,关于列表有如下几类基本操作。

拼接列表

  • 对两个列表aba+b会返回一个将它们拼接得到的新列表对象;
  • 对一个列表aa*3会将a重复3遍进行拼接,得到新的列表对象。
1
2
3
4
5
6
7
8
a = [1,2]
b = [3,4]
s = a + b
# s: [1,2,3,4]

a = [1,2]
s = a*3
# s: [1,2,1,2,1,2]

查找元素

  • 使用in查看指定元素是否在列表中(这也可以用于字符串中);
  • 使用s.count(x)可以查看元素x在列表s中出现的次数;
  • 使用s.index(x)可以查看元素x首次在列表s中出现的索引,如果不在列表中会报错。
1
2
3
4
5
6
7
8
s = ['a',1,'b',100,1]

1 in s # true
'x' in s # false
2 not in s # true

s.count(1) # 2
s.index('b') # 2

增加元素

  • 在末尾添加元素:a.append(x)
  • 在指定索引处添加元素:a.insert(3,x)
  • 在末尾添加指定列表的所有元素:a.extend(b)
1
2
3
4
5
6
7
8
9
a = [1,2,3]
a.append(4)
# a: [1,2,3,4]

a.insert(3,-1)
# a: [1,2,3,-1,4]

a.extend([-10,-20])
# a: [1, 2, 3, -1, 4, -10, -20]

移除元素

  • 移除指定元素:a.remove(x)(如果多次出现,只会移除第一次出现的项,如果没有出现则会报错);
  • 弹出指定索引处元素:a.pop(3),弹出的元素可以继续用于赋值:y = a.pop(3),注意索引缺省时会弹出最后一个元素。
1
2
3
4
5
6
7
8
9
10
11
a = [1,2,3,1]
a.remove(1)
# a: [2,3,1]

y = a.pop(1)
# y: 3
# a: [2,1]

z = a.pop()
# z: 1
# a:[2]

切片与索引

列表和字符串具有类似的索引和切片语法,这里关注两者的区别:

  • 与字符串不同,列表通过索引获取的项是可以修改的,例如

    1
    2
    3
    s = [1,2,3,4,5]
    s[0] = 10
    # s: [10,2,3,4,5]

  • 即使是对列表的切片也是可以修改的,但是要注意只能把列表赋值给切片,例如

    1
    2
    3
    4
    5
    s = [1,2,3,4,5]
    s[1:4] = [200]
    # s: [1,200,5]

    s[-2:] = 0 # 报错

  • 可以将切片赋值为空列表[],来达到到删除部分项的目的,例如

    1
    2
    3
    4
    5
    6
    7
    8
    s = [1,2,3,4,5,6]
    s[2:4] = []
    # s: [1,2,5,6]

    # 等价于使用del语句删除切片
    s2 = [1,2,3,4,5,6]
    del s2[2:4]
    # s2: [1,2,5,6]

注:如果切片不是连续的(即step不为1),则对切片的赋值必须保证两侧的数目一致。

其它操作

  • 列表翻转:a.reverse(),翻转会直接修改这个列表自身
  • 列表排序:a.sort(),排序会直接修改这个列表自身,如果希望获得排序后的副本,但是保留原始列表,可以使用b=sorted(a)

元组

元组可以视作列表的不可变版本,因此除了修改操作之外,都是类似的。 可以使用元组字面量来定义一个元组对象

1
2
s = (1,2,3)
s = () # 等价于 s = tuple()

可以基于一个列表来创建元组,反过来也是可以的

1
2
3
4
5
a = tuple([1,2,3])
# a: (1,2,3)

b = list(a)
# b: [1,2,3]

关于元组还有一个值得注意的细节,有时候加一个逗号的含义是不同的

1
2
3
4
5
a = (1) # 1
b = (1,) # (1,) 只有一个元素的元组

c, = (1,) # 将元组(1,)的第一个元素也是唯一的元素赋值给c
# c=1

字典

字典是存储键值对的数据结构,其中的键记作key,值记作value, value可以是任意的对象(包括字典本身),但是对key的对象类型有特殊要求,通常使用不可变的基本类型,例如数值,字符串或元组。在字典中会确保key是不可变的,并且具有唯一性。

可以使用字典字面量来定义一个字典对象

1
2
3
a = {'first': 'num 1', 'second': 'num 2', 3: 'num 3'}

a = {} # 等价于 a = dict()

读写键值对

字典采用与索引类似的方式来操作键值对,只是这里不再使用索引那样的整数,而是使用key进行。

对于存在的key可以直接读取和修改它的value,例如

1
2
3
4
5
6
7
8
9
a={'a':1,'b':2}

print(a['b']) # 2

a['a'] = 100
# a: {'a':100,'b':2}

a['b'] += 3
# a: {'a':100,'b':5}

对于不存在的key,尝试进行读取会报错,尝试进行赋值则会直接新建相应的键值对,例如

1
2
3
4
5
a={}
a['b']=1 # 不存在的key直接新建
# a: {'b':1}

a[2] # 报错,没有key等于2

使用get方法可以更安全地在字典中根据key获取value(只能读取,不能进行赋值),在key不存在时不会抛出错误,而是返回None,也可以指定为其它的默认值,例如

1
2
3
4
5
6
7
a={'a':1,'b':2}

a.get('b') # 2

a.get('c') # None

a.get('c',0) # 0

通过in也可以查询key是否在字典中,例如

1
2
3
4
a={'a':1,'b':2}

'c' in a # false
'a' in a # true

使用pop方法可以通过key移除指定的键值对,并且弹出value(可以用于赋值),例如

1
2
3
4
5
a = {'a':1,'b':2}

x = a.pop('b')
# x: 2
# a: {'a':1}

更新字典

可以使用update方法用一个字典来更新当前字典:a.update(b),更新的逻辑为:

  • 如果b中的key在a中没有出现,则添加键值对到a
  • 如果ab有公共的key,则使用b中的值替换a中的值

例如

1
2
3
4
5
a = {'x':1,'y':2}
b = {'y':-2,'z':-3}

a.update(b)
# a: {'x':1,'y':-2,'z':-3}

解包字典

可以将字典拆解为其它的数据类型:

  • a.keys() 返回一个由所有键组成的列表;
  • a.values() 返回一个由所有值组成的列表;
  • a.items() 返回一个由所有键值对元组组成的列表。

反过来,也可以通过一个由键值对元组组成的列表,来创建字典,例如

1
2
3
4
user = dict([('name', 'lili'),
('sex', 'female'),
('age', 32),
('address', 'beijing')])

值得注意的是,for语句直接遍历字典时,得到的是键而非值

1
2
3
4
5
6
7
a = {'x':1,'y':2}

for i in a:
print(type(i)," ",i," ",a[i])

# <class 'str'> x 1
# <class 'str'> y 2

集合

集合是存储互异元素的无序序列,可以保证元素的唯一性,并且只允许存放的是不可变对象(为保持确定性),Python对集合的实现与数学上的集合概念相当契合。

可以用集合字面量来定义一个集合对象

1
2
3
4
5
6
7
a = {1,2,3,4}
print(a)
# {1,2,3,4}

b = {1,2,1}
print(b)
# {1,2}

构造时如果字面量中出现重复元素,会自动去重。必须使用set()显式创建空集合

1
a = set()

集合间关系

两个集合可能存在包含关系,例如

1
2
3
4
5
6
a = {1,2,3}
b = {1,2}

b.issubset(a) # True

b <= a # True

这里可以通过issubset()方法,也可以通过<=运算符实现包含关系的判断。

甚至还支持使用<来判断真包含关系

1
2
3
4
a = {1,2,3}

a <= a # True
a < a # False

集合间运算

两个集合之间支持通常意义上的交集,并集,差集运算等,注意运算得到的结果只是作为返回值,并不会修改原本的集合对象。

并集运算例如

1
2
3
4
5
6
7
8
a = {1,2,3}
b = {2,3,4}

c = a.union(b)
# c = {1,2,3,4}

d = a | b
# d = {1,2,3,4}

这里既可以通过union()方法,也可以通过|运算符实现。

交集运算例如

1
2
3
4
5
6
7
8
a = {1,2,3}
b = {2,3,4}

c = a.intersection(b)
# c = {2,3}

d = a & b
# d = {2,3}

这里既可以通过intersection()方法,也可以通过&运算符实现。

差集运算例如

1
2
3
4
5
6
7
8
a = {1,2,3}
b = {2,3,4}

c = a.difference(b)
# c = {1}

d = a - b
# d = {1}

这里既可以通过difference()方法,也可以通过-运算符实现。

对称差集运算例如

1
2
3
4
5
6
7
8
a = {1,2,3}
b = {2,3,4}

c = a.symmetric_difference(b)
# c = {1,4}

d = a ^ b
# d = {1,4}

这里既可以通过symmetric_difference()方法,也可以通过^运算符实现。

添加元素

可以使用add()方法添加单个元素到集合中,注意如果集合中已经存在相同元素时,添加操作是无效的,但是不会报错

1
2
3
4
5
6
7
a = {1,2,3}

a.add(1)
# a = {1,2,3}

a.add(4)
# a = {1,2,3,4}

可以使用update()方法一次性添加多个元素到集合中

1
2
3
4
5
6
7
8
9
10
a = {1,2,3}

a.update([4,5])
# a = {1,2,3,4,5}

a.update((6,7))
# a = {1,2,3,4,5,6,7}

a.update({8,9})
# a = {1,2,3,4,5,6,7,8,9}

传入列表,元组或集合均可。

移除元素

可以使用remve()方法删除指定元素

1
2
3
a = {1,2,3}
a.remove(2)
# a={1,3}

如果使用pop()方法会移除集合中的一个元素,并且弹出(可以用于赋值),由于集合是无序的,因此不保证按照任何特定顺序弹出元素。