Python——第3章 列表、元组、字典、集合与字符串

发布时间 2023-05-04 00:32:35作者: 小平凡的记录

列表与列表推导式

list((3, 5, 7, 9, 11))       # 将元组转换为列表
[3, 5, 7, 9, 11]
list(range(1, 10, 2))        # 将range对象转换为列表
[1, 3, 5, 7, 9]
list(map(str, range(10)))    # 将map对象转换为列表
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
list(zip('abcd', [1,2,3,4])) # 将zip对象转换为列表
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
list(enumerate('Python'))    # 将enumerate对象转换为列表
[(0, 'P'), (1, 'y'), (2, 't'), (3, 'h'), (4, 'o'), (5, 'n')]
list(filter(str.isdigit, 'a1b2c3d456')) # 将filter对象转换为列表
['1', '2', '3', '4', '5', '6']
list('hello world')          # 将字符串转换为列表,每个字符转换为列中的一个元素
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
list({3, 7, 5})              # 将集合转换为列表,集合中的元素是无序的                          
[3, 5, 7]
x = list()                   # 创建空列表
x = [1, 2, 3]
del x                        # 删除列表对象

使用下标访问列表中的元素

data = list(range(10))
print(data)
print(data[0])              # 第一个元素的下标为0
print(data[1])              # 第二个元素的下标为1
print(data[-1])             # -1表示最后一个元素的下标
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0
1
9

列表常用方法

append()、insert()、extend()

lst = [1, 2, 3, 4]
lst.append(5)
lst.insert(0, 0)
lst.insert(2, 1.5)
lst.extend([6, 7])
print(lst)
[0, 1, 1.5, 2, 3, 4, 5, 6, 7]

pop()、remove()

lst = [1, 2, 3, 4, 5, 6]
print(lst.pop())            # 删除并返回最后一个元素
print(lst.pop(0))           # 删除并返回下标为0的元素,后面的元素向前移动
print(lst.pop(2))           # 删除并返回下标为2的元素,后面的元素向前移动
print(lst)
lst = [1, 2, 3, 2, 4, 2]
lst.remove(2)               # 删除第一个2,该方法没有返回值
print(lst)

6
1
4
[2, 3, 5]
[1, 3, 2, 4, 2]

count()、index()

lst = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
print(lst.count(2))       # 输出2
print(lst.index(4))       # 输出6
#print(lst.index(5))       # 代码抛出异常,提示5 is not in list
2
6

sort()、reverse()

from random import sample
data=sample(range(10000),10)# 在range(10000)中任选10个不重复的随机数
print(data)
[2092, 3910, 9114, 9169, 2810, 7072, 1344, 7294, 516, 8302]
data.reverse()# 翻转,首尾交换,该方法没有返回值
print(data)
[8302, 516, 7294, 1344, 7072, 2810, 9169, 9114, 3910, 2092]
data.sort()# 按元素大小进行排序,该方法没有返回值
print(data)
[516, 1344, 2092, 2810, 3910, 7072, 7294, 8302, 9114, 9169]
data.sort(key=str)# 按所有元素转换为字符串后的大小进行排序
print(data)
[1344, 2092, 2810, 3910, 516, 7072, 7294, 8302, 9114, 9169]

列表推导

data = [2**i for i in range(64)]
print(data)
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472, 274877906944, 549755813888, 1099511627776, 2199023255552, 4398046511104, 8796093022208, 17592186044416, 35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312, 1125899906842624, 2251799813685248, 4503599627370496, 9007199254740992, 18014398509481984, 36028797018963968, 72057594037927936, 144115188075855872, 288230376151711744, 576460752303423488, 1152921504606846976, 2305843009213693952, 4611686018427387904, 9223372036854775808]
#等价于
data = []
for i in range(64):
    data.append(2**i)
print(data)
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472, 274877906944, 549755813888, 1099511627776, 2199023255552, 4398046511104, 8796093022208, 17592186044416, 35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312, 1125899906842624, 2251799813685248, 4503599627370496, 9007199254740992, 18014398509481984, 36028797018963968, 72057594037927936, 144115188075855872, 288230376151711744, 576460752303423488, 1152921504606846976, 2305843009213693952, 4611686018427387904, 9223372036854775808]
data=[num for num in range(20) if num%2==1]
print(data)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
#等价于
data=[]
for num in range(20):
    if num%2==1:
        data.append(num)
print(data)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
from random import random

data = [[random() for j in range(5)] for i in range(3)]
print(data)
[[0.47725032702278103, 0.4965457868385723, 0.40963018073263124, 0.2591984399387045, 0.7171387333668126], [0.8656829892105975, 0.20652896789224207, 0.33007235688746295, 0.28071606988031217, 0.7122402398171469], [0.9037724065635463, 0.7253046535488346, 0.7100199352601256, 0.14821470797167746, 0.380343525451994]]
#等价于
from random import random

data = []
for i in range(3):
    temp = []
    for j in range(5):
        temp.append(random())
    data.append(temp)
print(data)
[[0.8180307526088073, 0.3935448868790832, 0.26053864269003346, 0.7565407979483234, 0.4774528772296447], [0.5423682793115739, 0.9268499207996582, 0.5712570815043689, 0.22171753085639834, 0.26065067502458994], [0.7251474502370134, 0.633555150364841, 0.9932162648389573, 0.5535546313735566, 0.8778307483985294]]

切片操作

切片是用来获取列表、元组、字符串等有序序列中部分元素的一种语法。在形式上,切片使用2个冒号分隔的3个数字来完成。
[start?step]

其中第一个数字start表示切片开始位置,默认为0;第二个数字end表示切片截止(但不包含)位置(默认为列表长度);第三个数字step表示切片的步长(默认为1),省略步长时还可以同时省略最后一个冒号。

当step为负整数时,表示反向切片,这时start应该在end的右侧。

data = list(range(20))
print(data[:])          # 获取所有元素的副本
print(data[:3])         # 前三个元素
print(data[3:])         # 下标3之后的所有元素
print(data[::3])        # 每3个元素选取1个
print(data[-3:])        # 最后3个元素
print(data[:-5])        # 除最后5个元素之外的所有元素
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 2]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[0, 3, 6, 9, 12, 15, 18]
[17, 18, 19]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

元组与生成器表达式

可以通过把若干元素放在一对圆括号中创建元组,如果只有一个元素的话则需要多加一个逗号,例如(3,)。

也可以使用tuple()函数把列表、字典、集合、字符串以及range对象、map对象、zip对象或其他类似对象转换为元组。

很多内置函数、标准库函数和扩展库函数也会返回元组或者包含元组的对象。

元组与列表的区别

元组是不可变的,不能直接修改元组中元素的值,也不能为元组增加或删除元素。因此,元组没有提供append()、extend()和insert()等方法,也没有remove()和pop()方法。

元组的访问速度比列表更快,开销更小。如果定义了一系列常量值,主要用途只是对它们进行遍历或其他类似操作,那么一般建议使用元组而不用列表。

元组可以使得代码更加安全。例如,调用函数时使用元组传递参数可以防止在函数中修改元组,而使用列表则无法保证这一点。

元组可用作字典的键,也可以作为集合的元素,但列表不可以,包含列表的元组也不可以。

生成器表达式

gen = (2**i for i in range(8))     # 创建生成器对象
print(gen)
print(list(gen))                   # 转换为列表,用完了生成器对象中的所有元素
print(tuple(gen))                  # 转换为元组,得到空元组
gen = (2**i for i in range(8))     # 重新创建生成器对象
print(next(gen))                   # 使用next()函数访问下一个元素
print(next(gen))
for item in gen:                   # 使用for循环访问剩余的所有元素
    print(item, end=' ')
<generator object <genexpr> at 0x000001FB94F53CF0>
[1, 2, 4, 8, 16, 32, 64, 128]
()
1
2
4 8 16 32 64 128 

序列解包

x, y, z = 1, 2, 3                 # 多个变量同时赋值
x, y, z = (False, 3.5, 'exp')     # 元组支持序列解包
x, y, z = [1, 2, 3]               # 列表支持序列解包
x, y = y, x                       # 交换两个变量的值
x, y, z = map(int, '123')         # map对象支持序列解包
data = {'a': 97, 'b': 98}
x, y = data.values()              # 使用字典的“值”进行序列解包
print(x,y)
97 98

字典

data = dict(name='张三', age=18, sex='M')
print(data)
data = dict.fromkeys([1, 2, 3, 4])    # 以指定的数据为“键”,“值”为空
print(data)
data = dict(zip('abcd', [97,98,99,100]))
print(data)
data = {ch:ord(ch) for ch in 'abcd'}  # 字典推导式
print(data)
{'name': '张三', 'age': 18, 'sex': 'M'}
{1: None, 2: None, 3: None, 4: None}
{'a': 97, 'b': 98, 'c': 99, 'd': 100}
{'a': 97, 'b': 98, 'c': 99, 'd': 100}

字典元素的访问

data = dict(name='张三', age=18, sex='M')
print(data['name'])                         # 使用“键”作为下标,访问“值”
print(data.get('age'))
print(data.get('address', '不存在这个键'))   # “键”不存在,返回默认值
print(list(data))                           # 把所有的“键”转换为列表
print(list(data.values()))                  # 把所有的“值”转换为列表
print(list(data.items()))                   # 把所有的元素转换为列表
for key, value in data.items():             # 遍历字典的“键:值”元素
    print(key, value, sep='\t')
张三
18
不存在这个键
['name', 'age', 'sex']
['张三', 18, 'M']
[('name', '张三'), ('age', 18), ('sex', 'M')]
name	张三
age	18
sex	M

字典元素的修改、添加与删除

当以指定“键”为下标为字典元素赋值时,有两种含义:

1)若该“键”存在,表示修改该“键”对应的值;

2)若不存在,表示添加一个新元素。

sock = {'IP': '127.0.0.1', 'port': 80}
sock['port'] = 8080                  # 修改已有元素的“值”
sock['protocol'] = 'TCP'             # 增加新元素
print(sock)
{'IP': '127.0.0.1', 'port': 8080, 'protocol': 'TCP'}

使用字典对象的update()方法可以将另一个字典的元素一次性全部添加到当前字典对象,如果两个字典中存在相同的“键”,则以另一个字典中的“值”为准对当前字典进行更新。

sock={'IP':'127.0.0.1','port':80}
sock.update({'IP':'192.168.9.62','protocol':'TCP'})#更新已有元素,新添元素
print(sock)
{'IP': '192.168.9.62', 'port': 80, 'protocol': 'TCP'}

可以使用字典对象的pop()删除指定“键”对应的元素,同时返回对应的“值”。字典方法popitem()方法用于删除并返回一个包含两个元素的元组,其中的两个元素分别是字典元素的“键”和“值”。另外,也可以使用del删除指定的“键”对应的元素。

sock={'IP': '127.0.0.1', 'port': 80, 'protocal': 'TCP'}
print(sock.pop('IP'))#删除指定元素,并返回指定键的值
print(sock.popitem())#删除并返回一个元素
del sock['port']#删除指定键的元素
print(sock)
127.0.0.1
('protocal', 'TCP')
{}

集合

Python集合是无序、可变的容器对象,所有元素放在一对大括号中,元素之间使用逗号分隔,同一个集合内的每个元素都是唯一的,不允许重复。

集合中只能包含数字、字符串、元组等不可变类型的数据,而不能包含列表、字典、集合等可变类型的数据,包含列表等可变类型数据的元组也不能作为集合的元素。

集合中的元素是无序的,元素存储顺序和添加顺序并不一致。

集合不支持使用下标直接访问特定位置上的元素,也不支持使用random中的choice()函数从集合中随机选取元素,但支持使用random模块中的sample()函数随机选取部分元素。

集合常用方法

1.add()、update()

data = {30, 40, 50}
data.add(20)               # 增加新元素20
data.add(50)               # 集合中已包含50,忽略本次操作
data.update({40, 60})      # 忽略40,增加新元素60
print(data)
{50, 20, 40, 60, 30}

pop()、remove()、discard()

data = {30, 40, 50}
data.remove(30)          # 删除元素30
data.discard(30)         # 集合中没有30,忽略本次操作
print(data.pop())        # 删除并返回集合中的一个元素
print(data)
40
{50}

字符串常用方法

字符串属于不可变对象,所有方法都是返回处理后的字符串或字节串,不对原字符串进行任何修改。

encode()

bookName = '《Python可以这样学》'
print(bookName.encode())
print(bookName.encode('gbk'))
print(bookName.encode('gbk').decode('gbk'))
b'\xe3\x80\x8aPython\xe5\x8f\xaf\xe4\xbb\xa5\xe8\xbf\x99\xe6\xa0\xb7\xe5\xad\xa6\xe3\x80\x8b'
b'\xa1\xb6Python\xbf\xc9\xd2\xd4\xd5\xe2\xd1\xf9\xd1\xa7\xa1\xb7'
《Python可以这样学》

format()

# 0表示format()方法的参数下标,对应于第一个参数
# .4f表示格式化为实数,保留4位小数
print('{0:.4f}'.format(10/3))
print('{0:.2%}'.format(1/3))
# 格式化为百分数字符串,总宽度为10,保留2位小数,>表示右对齐
print('{0:>10.2%}'.format(1/3))
# 逗号表示在数字字符串中插入逗号作为千分符,#x表示格式化为十六进制数
print("{0:,} in hex is: {0:#x}, in oct is {0:#o}".format(5555555))
# 可以先格式化下标为1的参数,再格式化下标为0的参数
# o表示八进制数,但不带前面的引导符0o
print("{1} in hex is: {1:#x}, {0} in oct is {0:o}".format(6666, 66666))
# _表示在数字中插入下画线作为千分符
print('{0:_},{0:#_x}'.format(10000000))
# 字符串前面加字符f,Python 3.6之后的版本支持这种用法
width = 8
height = 6
print(f'Rectangle of {width}*{height}\nArea:{width*height}')
3.3333
33.33%
    33.33%
5,555,555 in hex is: 0x54c563, in oct is 0o25142543
66666 in hex is: 0x1046a, 6666 in oct is 15012
10_000_000,0x98_9680
Rectangle of 8*6
Area:48

index()、rindex()、count()

text = '处处飞花飞处处;声声笑语笑声声。'
print(text.rindex('处'))
print(text.index('声'))
print(text.count('处'))
6
8
4

replace()、maketrans()、translate()

text = "Python是一门非常棒的编程语言。"
# replace()方法返回替换后的新字符串,可以直接再次调用replace()方法
print(text.replace('棒','优雅').replace('编程', '程序设计'))
print(text)
Python是一门非常优雅的程序设计语言。
Python是一门非常棒的编程语言。
table=''.maketrans('0123456789','零一二三四伍陆柒捌玖')#生成字符映射表
print('Tel:30647359'.translate(table))#根据字符映射表中定义的对应关系转换字符串并替换其中的字符串
Tel:三零陆四柒三伍玖

ljsut()、rjust()、center()

print('居左'.ljust(20)+'结束')
print('居右'.rjust(20, '#'))        # 左侧使用井号填充
print('居中'.center(20, '='))       # 两侧使用等号填充
居左                  结束
##################居右
=========居中=========

split()、rsplit()、join()

text = 'Beautiful is better than ugly.'
print(text.split())                     # 使用空白字符进行分隔
print(text.split(maxsplit=1))           # 最多分隔一次
print(text.rsplit(maxsplit=2))          # 最多分隔两次
print('1,2,3,4'.split(','))             # 使用逗号作为分隔符
print(','.join(['1', '2', '3', '4']))   # 使用逗号作为连接符
print(':'.join(map(str, range(1, 5))))  # 使用冒号作为连接符
print(''.join(map(str, range(1, 5))))   # 直接连接,不插入任何连接符
['Beautiful', 'is', 'better', 'than', 'ugly.']
['Beautiful', 'is better than ugly.']
['Beautiful is better', 'than', 'ugly.']
['1', '2', '3', '4']
1,2,3,4
1:2:3:4
1234

lower()、upper()、capitalize()、title()、swapcase()

text = 'Explicit is better than implicit.'
print(text.lower())
print(text.upper())
print(text.capitalize())
print(text.title())
print(text.swapcase())
explicit is better than implicit.
EXPLICIT IS BETTER THAN IMPLICIT.
Explicit is better than implicit.
Explicit Is Better Than Implicit.
eXPLICIT IS BETTER THAN IMPLICIT.

startwith()、endswith()

text = 'Simple is better than complex.'
print(text.startswith('simple'))
print(text.startswith('Simple'))
print(text.endswith(('.', '!', '?')))
False
True
True

strip()、rstrip()、lstrip()

text = '   ======test===#####   '
print(text.strip())          # 删除两侧的空白字符
print(text.strip('=# '))     # 删除两侧的=、#和空格
======test===#####
test
print(text.strip('=# '))
text

综合应用

data=[2**i for i in range(64)]
print(sum(data))
18446744073709551615
data=eval(input('请输入一个包含若干整数的列表:'))
print([num for num in data if num%2==1] )
请输入一个包含若干整数的列表:[2,5,4,67,8,6]
[5, 67]
vector1=eval(input('请输入一个包含若干整数的向量:'))
vector2=eval(input('请再输入一个包含若干整数的等长向量:'))
print(sum([num1*num2 for num1,num2 in zip(vector1,vector2)]))
请输入一个包含若干整数的向量:[2,5,4,67,8,6]
请再输入一个包含若干整数的等长向量:[2,5,4,67,8,3]
4616
data=eval(input('请输入一个包含若干整数的列表:'))
m=max(data)
print(m)
print([index for index,value in enumerate(data) if value==m])
请输入一个包含若干整数的列表:[2,5,4,67,8,6]
67
[3]
from string import digits
from random import choice
z=''.join(choice(digits) for i in range(1000))
result={}
for ch in z:
    result[ch]=result.get(ch,0)+1
for digit,fre in sorted(result.items()):
    print(digit,fre,sep=':')
0:88
1:118
2:94
3:104
4:125
5:95
6:115
7:88
8:90
9:83
text=input('请输入一个字符串:')
result=''.join(sorted(set(text),key=lambda ch:text.index(ch)))
print(result)
请输入一个字符串:《Python可以这样学》
《Python可以这样学》
A=eval(input('请输入一个集合:'))
B=eval(input('再输入一个集合:'))
print('并集:',A|B)
print('交集:',A&B)
print('对称差集:',A^B)
print('差集A-B:',A-B)
print('差集B-A:',B-A)
请输入一个集合:{50, 20, 40, 60, 30}
再输入一个集合:{50, 20, 40, 60, 25}
并集: {40, 50, 20, 25, 60, 30}
交集: {40, 50, 20, 60}
对称差集: {25, 30}
差集A-B: {30}
差集B-A: {25}
text=input('请输入一个包含空格的字符串:')
print(' '.join(text.split()))
请输入一个包含空格的字符串:《Python 可以这样学》
《Python 可以这样学》
text=input('请输入一个字符串:')
table=''.maketrans('aeoiu','AEOIU')
print(text.translate(table))
请输入一个字符串:《Python可以这样学》
《PythOn可以这样学》
import random
data1=[random.randint(1,10)]*5
data2=random.choices(range(10),k=5)
data3=random.sample(range(10),k=5)
for data in (data1,data2,data3):
    print('='*20)
    print(data)
    k1=len(set(data))
    k2=len(data)
    if k1==k2:
        print('无重复')
    elif k1==1:
        print('完全重复')
    else:
        print('部分重复')
====================
[3, 3, 3, 3, 3]
完全重复
====================
[3, 9, 5, 8, 7]
无重复
====================
[6, 4, 3, 5, 0]
无重复