Python3入门2--列表、元组等数据结构、字符串驻留机制及字符串格式化操作

第一章 变量、常用循环体、代码结构、代码练习

第二章 列表、元组等数据结构、字符串驻留机制及字符串格式化操作

第三章 函数、面向对象、文件操作、深浅拷贝、模块、异常及捕获

第四章 项目打包、类和对象高级、序列、迭代器、生成器、装饰器

第五章 正则表达式、json、logging日志配置、数据库操作、枚举、闭包、匿名函数和高阶函数、time、datetime

第六章 Socket编程、多线程(创建方式、线程通信、线程锁、线程池)

列表、元组、字典、集合

列表

为什么需要列表?

变量可以存储一个元素,而列表是一个 大容器可以存储N多个元素(不同数据类型),程序可以方便地对这些数据进行整体操作

列表有两种索引方式:如下图

在这里插入图片描述

内存示例

代码示例:

a = 10  # 变量存储的是一个对象的引用(标识)
lst = ['hello', 'world', 98] # 存储多个对象的引用(标识)
print(lst)

图示:(以下id标识自编的不真实)

一个list列表中,存储的是多个对象的引用标识(id)

在这里插入图片描述

列表的创建

  • 使用中括号,[],括号中的元素使用 ,分隔
  • 使用内置函数list()
# 第一种方式,使用[]
lst = [1, 2, 3]
# 第二种方式,使用内置函数 list()
lst2 = list([1, 2, 3])

# 空列表
a = []
a = list()

列表的特点

  • 列表元素按顺序有序排列
  • 索引映射唯一一个数据
  • 列表可存储重复数据
  • 任意类型数据
  • 根据需要动态分配和回收内存
lst = ['hello', 'hello', 1 , 2]
print(lst)
print(lst[0])

# 输出结果
['hello', 'hello', 1, 2]
hello

列表的操作

获取列表中元素的索引值

元素不存在时,报错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ozu2Yd7G-1648189429633)(imgs/16.png)]

lst = ['hello', 'hello', 1 , 2]
print(lst.index('hello')) # 找第一个'hello'元素的索引值
print(lst.index('hello', 1, 3)) # 在列表lst的索引1-3范围内,找第一个'hello'的索引值

获取列表中单个元素

索引不存在,报错

在这里插入图片描述

lst = ['hello', 'world', 'hello', 200, 300]
# 获取 'world' 元素
print(lst[1])
print(lst[-4])

获取列表多个元素(切片操作)

返回值为一个新的列表,就是原列表片段的拷贝(在内存开空间存储新的元素)。

在这里插入图片描述

lst = [10, 20, 30, 40, 50, 60, 70, 80]
# 截取 30-60  要注意切片的范围是  [start,stop) 半闭半开区间
print(lst[2:6:1])

lst[:6:] # 这种写法== [0:6:1],都取的默认值

判断元素是否存在

元素 in 列表
元素 not in 列表
lst = [10, 20, 30, 40, 50, 60, 70, 80]
print(100 in lst) # False
print(10 in lst)  # True

列表元素遍历

for 迭代变量 in 列表:
    循环体
lst = [10, 20, 30, 40, 50, 60, 70, 80]
for item in lst:
    print(item)

列表元素的增加操作

在这里插入图片描述

  • append()

    使用append()后,向列表末尾添加一个元素,并且不会改变列表对象(标识),没有产生新的列表对象

lst =[10, 20, 30]
# 向列表末尾添加一个元素
lst.append(40) 
print(lst)    # [10, 20, 30, 40]
  • extend() 批量添加
lst =[10, 20, 30]

# 向列表末尾添加一个列表元素
lst2 = ['hello', 'world']
lst.append(lst2)
print(lst)  # [10, 20, 30, ['hello', 'world']]

# 向列表末尾添加至少一个元素(扩展添加)
lst =[10, 20, 30]
lst.extend(lst2)
print(lst)  # [10, 20, 30, 'hello', 'world']
  • insert

索引不存在时,不会报错

索引值不存在时,索引值为负数,则将元素添加至第一位,索引是整数,则添加至最后一位

lst =[10, 20, 30]
lst.insert(1,100)  # 在索引为 1 的位置上添加 元素 100
print(lst)
  • 切片操作

注意,以下并没有创建新的列表对象,lst的id标识没有改变

lst = [10, 20, 30, 40, 50, 60, 70, 80]
lst2 = ['hello','world', 'json']
lst[1:] = lst2	# 把索引从1开始的lst中所有元素替换成 lst2中的所有元素
print(lst)  # [10, 'hello', 'world', 'json']

列表删除元素操作

在这里插入图片描述

  • remove() 刪除一个元素

    从列表中删除第一个匹配的元素

    如果元素不存在,则会报错

    lst = [10, 20, 30, 40, 50, 60, 70, 80]
    lst.remove(30)
    print(lst)
    
  • pop() 根据索引移除元素

    索引不存在,报错

    不指定索引,删除列表最后一个元素

    lst = [10, 20, 30, 40, 50, 60, 70, 80]
    lst.pop()
    print(lst)	# [10, 20, 30, 40, 50, 60, 70]
    lst.pop(0)
    print(lst)	# [20, 30, 40, 50, 60, 70]
    
  • 切片

    一次至少删除一个元素,但是会产生新的列表对象

    就是列表元素的截取,然后生成新的列表对象

    lst = [10, 20, 30, 40]
    lst2 = lst[1:3]
    print(lst)		#[10, 20, 30, 40]
    print(lst2)		#[20, 30]
    
  • 不产生新对象,删除元素

    lst = [10, 20, 30, 40]
    lst[1:3] = []		# 只把lst中的 第二个元素和第三个元素 换成空列表
    print(lst)	# [10, 40]
    
  • clear()

    清空列表

    lst = [10, 20, 30, 40]
    lst.clear()
    print(lst)	# [] 空列表
    
  • del 删除列表对象

    del lst
    print(lst)	# NameError: 'lst' is not defined 报错
    

列表修改元素

  • 一次修改一个值
lst = [10, 20, 30, 40]

# 根据索引修改
lst[1] = 100
print(lst)

图示内存模型

在这里插入图片描述

  • 一次修改多个值

    lst = [10, 20, 30, 40]
    print(lst)	# [10, 20, 30, 40]
    lst[1:3] = [100, 200, 300, 400]
    print(lst) 	# [10, 100, 200, 300, 400, 40]
    

    把第二个元素和第三个元素去掉,替换成了 100,200,300,400

列表元素的排序

两种方式:

  • sort()方法,所有元素默认升序排序,可指定 reverse=True降序排序,不会产生新对象
  • sorted()内置函数,可指定 reverse=True降序排序,将会产生新的列表对象
# 使用sort()方法  不产生新对象
lst = [40, 20, 20, 10, 30]
lst.sort()
print(lst)		# [10, 20, 20, 30, 40]
lst.sort(reverse=True)
print(lst)		# [40, 30, 20, 20, 10]

# 使用sorted()内置函数	产生新对象
lst = [40, 20, 20, 10, 30]
sorted(lst)
print(lst)		# [10, 20, 20, 30, 40]
sorted(lst, reverse=True)
print(lst)		# [40, 30, 20, 20, 10]

列表生成式

在这里插入图片描述

# 产生1-9的列表对象
lst = [i for i in range(1, 10)]
print(lst)

# 值为乘本身
lst = [i*i for i in range(1, 10)]
print(lst)

字典

内存示例

在这里插入图片描述

字典:是Python内置的数据结构之一,与列表一样是一个可变序列

以键值对的方式存储数据,字典是一个无序的序列

语法示例:

在这里插入图片描述

特点

字典是无序的

字典中的所有元素都是k-v对,key不许重复(key重复,则会值覆盖,但是key还是只有一个),value可以重复

字典的key值是不可变序列,同字符串和整数类型一样都是不可变序列

字典可以根据需要动态的伸缩

字典会比较浪费较大的内存,是一种使用空间换时间的数据结构

实现原理

字典的实现原理和查字典类似,Python中字典是根据key查找value所在的位置。而这个key需要经过hash()函数计算得来,找到key后,直接获取到value

字典的创建

  • {}创建
  • dict() 内置函数创建
scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
print(scores)
scores = dict(name='jack', age=20)
print(scores)

sc = {
    
    } # 空字典
sc = dict()

字典的操作

获取字典中的元素

两种方式

在这里插入图片描述

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
age = scores.get('age')
gender = scores['gender']
print(age)		# 23
print(gender)	# 男

两种的区别:

scores['gender']这种方式不存在时会报错

scores.get('age')这种方式会返回 None

get(),读取不到时,可设置默认值

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
aaa = scores.get('aaa', 'wlh')
print(aaa)	# wlh

判断key是否存在

  • in
  • not in
scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
print('aaa' in scores)	# False

字典元素的删除

del,删除指定的 k-v对

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
del scores['age']
print('age' in scores)	# False,因为已经删除了 'age'的key

scores.clear()	# 清空
print(scores)	# {}

字典元素新增

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
scores['wlh'] = 888
print(scores)	# {'age': 23, 'name': 'zs', 'gender': '男', 'wlh': 888}

字典元素修改

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
scores['wlh'] = 888
scores['wlh'] = 999
print(scores['wlh'])	# 999

获取字典视图

在这里插入图片描述

  • keys() 获取所有key
  • values() 获取所有value
  • items() 获取所有键值对k-v对
scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
print(scores.keys())	# dict_keys(['age', 'name', 'gender'])
print(scores.values())	# dict_values([23, 'zs', '男'])
print(scores.items())	# dict_items([('age', 23), ('name', 'zs'), ('gender', '男')])

注意:这里获取到的并不是list类型的,我们可以把这些类型转换成list列表

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
print(list(scores.keys()))		# ['age', 'name', 'gender']
print(list(scores.values()))	# [23, 'zs', '男']
print(list(scores.items()))		# [('age', 23), ('name', 'zs'), ('gender', '男')]

字典元素的遍历

scores = {
    
    'age': 23, 'name': 'zs', 'gender': '男'}
for i in scores:    # 这里注意 i 是key 的值
    print(i, scores[i], scores.get(i))

字典生成式

在这里插入图片描述

使用内置函数zip()

用于将可迭代的对象最为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表

items = ['Fruits', 'Books', 'Others']
prices = [96, 78, 85]
d = {
    
     item:price for item,price in zip(items, prices)}	# 以item为key,price为value生成字典
e = {
    
     item.upper():price for item,price in zip(items, prices)}
print(d)	# {'Fruits': 96, 'Books': 78, 'Others': 85}
print(e)	# {'FRUITS': 96, 'BOOKS': 78, 'OTHERS': 85}

元组

元组是Python内置的数据结构之一,是一个不可变序列

在这里插入图片描述

元组的创建

  • ()创建

    如果元组中只有一个元素,一定要加上逗号,

  • 使用内置函数tuple()

# ()创建
t = ('hello', 'world', 90)	
print(t)	# ('hello', 'world', 90)

# ()可省略
t1 = 'Hello', 'world', 98
print(t1)	# ('Hello', 'world', 98)

# 注意,这样子写,会认为是str类型
ts = ('Hello')
print(type(ts))	# <class 'str'>
# 要加一个 逗号
ts = ('hello',)
print(type(ts))	# <class 'tuple'>

t2 = tuple(('hello', 'world', 98))
print(t2)	# ('hello', 'world', 98)

# 空元组创建
t = ()
t = tuple()

元组中获取数据

和列表一致,都是通过下标获取即可

t = (10, [23,30], 9)
print(t[1])	# [23, 30] 是一个list列表

为什么将元组设计为不可变序列

  • 多任务环境下,同时操作对象不需要加锁
  • 在程序中尽量使用不可变序列

注意:

元组中存储的是对象的引用

  • 如果元组中对象本身是不可变对象,则不能再引用其他对象
  • 如果元组中对象是可变对象,则可变对象的引用不允许改变,但是数据可以改变

在这里插入图片描述

注意:元组中引用的对象不能发生改变,不管引用对象是可变还是不可变

可变对象的引用中,值可以改变,但是引用不能

t = (10, [23,30], 9)
# 错误写法
t[1] = 100
print(t)

# 正确写法 列表中添加元素
t[1].append(100)
print(t)

元组的遍历

for-in 遍历

t = (10, [23,30], 9)
for i in t:
    print(i, end='\t')	# 10	[23, 30]	9

集合

集合中的元素不能重复,会自动去重

在这里插入图片描述

  • 可变类型的序列

  • 集合是没有value的字典

  • key的位置,同样是使用hash函数计算得出

集合的创建

  • 直接使用{}

  • 使用内置函数set()

# 通过{}
s = {
    
    2, 3, 4, 5, 5}
print(s)

# 通过set()内置函数
s1 = set(range(6))
print(s1)

# 通过set() 将list转为set集合
s2 = set([1,2,3,4])
print(s2)

# 将元组 转为set集合
s3 = set(('Python', 2, 5))
print(s3)

# 将字符串转为set集合(字符分割)
s4 = set('Python')
print(s4)

s5 = set({
    
    1,2,3,4,5})
print(s5)

# 定义空集合 只能使用 set()的方式
s6 = set()

集合的操作

集合元素判断操作

  • in 和 not in
s = {
    
    10, 20, 30, 40}
print(10 in s)		# True
print(100 not in s) # True

集合元素新增操作

  • add() 方法,一次添加一个元素
  • update() 方法,至少添加一个元素(批量添加)
# 单值添加
s = {
    
    10, 20, 30, 40}
s.add(50)
print(s)	# {40, 10, 50, 20, 30}

# 批量添加
s.update({
    
    60, 70, 80})
print(s)	# {70, 40, 10, 80, 50, 20, 60, 30}

# 也可以添加元组、列表等可迭代对象的元素
s.update([1,3,5])
s.update(('Python','hello',98))

集合的删除操作

  • remove()方法,一次删除一个指定元素,如果元素不存在,则抛出异常
  • discard() 一次删除一个指定元素,如果不存在,不抛出异常
  • pop() 一次只删除一个任意元素
  • clear() 清空集合

集合之间的关系

在这里插入图片描述

# 两集合是否相等,元素相同就相等
s1 = {
    
    10, 20, 30, 40}
s2 = {
    
    40, 30, 20, 10}
print(s1 == s2) # True

s1 = {
    
    10, 20, 30, 40}
s2 = {
    
    40, 30, 20}
# s2是s1的子集
print(s2.issubset(s1))  # True

# s1是s2的超集(父集)
print(s1.issuperset(s2)) # True

# 两个集合是否 没有交集
print(s1.isdisjoint(s2))	# False

集合数学操作

在这里插入图片描述

交集

  • intersection()方法
  • & 操作符
s1 = {
    
    10, 20, 30}
s2 = {
    
    20, 30, 40, 50}
print(s1.intersection(s2))
print(s1 & s2)

并集

  • union()方法
  • | 操作符
# 并集
print(s1.union(s2))
print(s1 | s2)

差集

比如 A比较B的差集,就是只取在 A中 B没有的元素

  • difference()方法
  • -操作符
# 差集
print(s1.difference(s2))
print(s1 - s2)

对称差集

取两集合,互相没有的元素

  • symmetric_difference() 方法
  • ^操作符
# 对称差集
print(s1.symmetric_difference(s2))
print(s1 ^ s2)

集合生成式

在这里插入图片描述

s = {
    
    i for i in range(6)}
print(s)	# {0, 1, 2, 3, 4, 5}

列表、元组、字典、集合总结

在这里插入图片描述

可变序列和不可变序列

  • 不可变序列:没有增删改的操作

    字符串、元组、整数

  • 可变序列:可以对序列执行增删改操作,且对象的地址不会发生改变

    列表、字典、集合

字符串

字符串的驻留机制

字符串是一个基本数据类型,是一个不可变的字符序列

驻留机制:

仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建的相同字符串时,不会开辟新的空间,而是把已存在的字符串地址赋给新创建的变量。

在这里插入图片描述

  • 驻留机制的几种情况,以下情况会让多变量指向同一个内存空间 (交互模式下看,PyCharm对这些做了优化)

    • 字符串长度为0或1

    • 符合标识符的字符串

    • 字符串只在编译时进行驻留,而非运行时

      • a = 'abc'
        b = 'ab' + 'c'
        c = ''.join(['ab', 'c'])
        
        print(a is b) # True	b的创建,在编译时就已经连接好了
        print(a is c) # False	c的创建,是程序运行时才连接好'abc'值
        
    • [-5,256]之间的整数数字

      • a = -5
        b = -5
        print(a is b) # True
        
        a = -6
        b = -6
        print(a is b) # False
        
  • sys中intern()方法,强制2个字符串指向同一个对象

    • import sys
      s1 = 'abc%' # 不符合标识符的字符串(正常情况下不被驻留)
      s2 = s1.intern(s1)
      print(s1 is s2) # True 强制驻留
      
  • PyCharm对字符串进行了优化处理

驻留机制的优缺点

  • 当需要值相同的字符串时,可以直接从字符串池里拿出来用,避免频繁的创建和销毁,提升效率节约内存,因此拼接字符串和修改字符串时会比较影响性能的
  • 在需要进行字符串的拼接时,建议使用str类型的join()方法,而非 +,因为 join()方法是先计算出所有字符串中的长度,然后进行拷贝,只new一次对象,效率要比+

字符串的常用操作

字符串的查找

在这里插入图片描述

  • index() 查元素第一次出现的索引位置,不存在报错
  • rindex() 查元素最后一次出现的索引位置,不存在报错
  • find() 查元素第一次出现的索引位置,不存在返回 -1
  • rfind() 查元素最后一次出现的索引位置,不存在返回 -1

建议使用 find()rfind()方法

s = 'hello,hello'
print(s.index('lo'))	# 3
print(s.find('lo'))		# 3

print(s.rindex('lo'))	# 9
print(s.rfind('lo'))	# 9

print(s.index('k'))		# 报错
print(s.find('k'))		# 返回 -1

字符串的大小写转换

在这里插入图片描述

转换后,会生成新的字符串对象

  • upper()
  • lower()
  • swapcase()
  • title()
s = 'hello,python'
a = s.upper()   # 转大写,会生成新对象
print(a)		# HELLO,PYTHON

b = a.lower()   # 转小写,会生成新对象
print(b)		# hello,python

s2 = 'hello,Python'
print(s2.swapcase()) # 大写转小写,小写转大写	HELLO,pYTHON

print(s2.title())   # 每个单词的首字母大写,其他小写	Hello,Python

字符串对齐操作

注意:如果指定的字符串长度,小于原字符串长度,那么将直接返回原字符串,不会进行填充操作。

在这里插入图片描述

s = 'hello,Python'
print(s.center(20, '*'))    # 字符串居中,总长度20,剩余 '*' 补齐		****hello,Python****

print(s.ljust(20, '*'))     # 字符串左对齐,总长度20,剩余 '*' 补齐	hello,Python********

print(s.rjust(20, '*'))     # 字符串右对齐,总长度20,剩余 '*' 补齐	********hello,Python

print(s.zfill(20))          # 字符串右对齐,总长度20,剩余 '0' 补齐	00000000hello,Python

字符串分割

如果不声明以什么字符分割,则会默认 空格字符串,返回一个列表

在这里插入图片描述

  • split()方法
s = 'hello world Python'
a = s.split()		# 从左边分割,默认空格分割
print(a)			# ['hello', 'world', 'Python']

s1 = 'hello|world|Python'
a2 = s1.split('|')	# 以 '|' 分割
print(a2)			# 

a3 = s1.split('|', 1)	# 以 '|' 分割,且只分割一次
print(a3)			# ['hello', 'world|Python']
  • rsplit() 方法
s1 = 'hello|world|Python'
a2 = s1.rsplit('|')	# 从右边以'|'分割
print(a2)			# ['hello', 'world', 'Python']

a3 = s1.rsplit('|', 1)		# 从右边以'|'分割,只分割一次
print(a3)			# ['hello|world', 'Python']	

注意点: 如果未指定最大分割次数,那么split()和rsplit()效果一样,如果指定最大分割次数,那么要注意两个方法的执行效果可能不一致。

字符串判断

在这里插入图片描述

s = 'hello,world'

# 是否是合法标识字符串
print(s.isidentifier())         # False
print('hello'.isidentifier())   # True

# 是否全部为空白字符
print('   '.isspace())          # True

# 全部是字母?
print('abc'.isalpha())          # True
print('张三'.isalpha())          # True 

# 全部是 十进制 数字?
print('1234'.isdecimal())       # True
print('12三'.isdecimal())       # False

# 全部是数字?
print('122'.isnumeric())        # True
print('12三'.isnumeric())        # True 不只中文数字,罗马数字同样可以

# 由 数字和字母组成?
print('safds112张三'.isalnum())   # True     
print('safds112张三!'.isalnum())  # False 有个'!'

字符串的替换与合并

在这里插入图片描述

  • replace()
s = 'Hello,Python'
print(s.replace('Python', 'Java'))      # 将'python'替换为'Java'    Hello,Java

s = 'Hello,Python,Python,Python'
print(s.replace('Python', 'Java', 2))   # 将'python'替换为'Java',只替换2个  Hello,Java,Java,Python
  • join()
lst = ['Java', 'Python', 'Go']
print('|'.join(lst))        # Java|Python|Go
print(''.join(lst))         # JavaPythonGo
print("|".join('Python'))   # P|y|t|h|o|n

字符串的比较

在这里插入图片描述

print('apple' > 'app')  # True
print('apple' > 'banana')   # False

# 原理就是 挨个比较 单个字符的 原始值(可用ord()内置函数获取)
print(ord('a'), ord('b'))   # a = 97 b = 98 所以

# chr() 可以获取原始值对应的 字符
print(chr(97), chr(98)) # a  b

== 和 is 的区别

==:比较的是内容是否相等

is : 比较的是内存地址(id标识)是否相等

字符串的切片操作

字符串是不可变类型

  • 不具备 增删改操作
  • 切片后将产生新的对象
# 每切一次都会产生新的对象
s = 'hello,Python'
print(s[:5:1])    # 默认从0开始切,步长默认1(可省略)			# hello
print(s[6::1])    # 默认切到最后一个最值,步长默认1(可省略)    # Python

# 步长为负数
print(s[::-1]) # 默认从字符串最后一位置开始,因为步长是负数      # nohtyP,olleh

# 索引为负数
print(s[-6::1]) # 从-6位置开始,到字符串最后结束,步长为1     # Python

格式化字符串

在这里插入图片描述

  • %占位符
  • {}占位符
  • f-string
name = '张三'
age = 21

# % 占位符
print('我的名字是%s,今年%d岁了' % (name, age))
print('%.3f' % 3.1415826)	# 保留3位小数
print('%10.3f' % 3.1415926) # 总长度10,并且保留3位小数

# {} 占位符
print('我的名字是{0},今年{1}岁了'.format(name, age))

# f-String python3新增
print(f'我的名字是{
      
      name},今年{
      
      age}岁了')

print('{0:.3}'.format(3.1415926)) # 3.14 保留3位有效数字
print('{:.3f}'.format(3.1415926)) # 3.142 保留3为小数
print('{:10.3f}'.format(3.1415926)) # 总长度10,并且保留3位小数

字符串编码转换

为什么要进行字符串的编码转换

在这里插入图片描述

编码和解码

  • 编码:将字符串转换为二进制数据(bytes)
  • 解码:将bytes类型的数据转换成字符串类型

注意,编码和解码时,使用相同的编码格式。。

s = '天涯共此时'
# 编码
print(s.encode('GBK'))  # GBK这种编码格式,一个中文占用 两个字节
print(s.encode('UTF-8')) # UTF-8 一个中文占用 三个字节

# 解码
byte1 = s.encode('GBK')
print(byte1.decode('GBK'))



第一章 变量、常用循环体、代码结构、代码练习

第二章 列表、元组等数据结构、字符串驻留机制及字符串格式化操作

第三章 函数、面向对象、文件操作、深浅拷贝、模块、异常及捕获

第四章 项目打包、类和对象高级、序列、迭代器、生成器、装饰器

第五章 正则表达式、json、logging日志配置、数据库操作、枚举、闭包、匿名函数和高阶函数、time、datetime

第六章 Socket编程、多线程(创建方式、线程通信、线程锁、线程池)

猜你喜欢

转载自blog.csdn.net/weixin_45248492/article/details/123734802