Day08 Python数据结构(数据容器)详解

news2024/11/23 13:50:56

文章目录

    • 第五章 Python数据容器
      • 5.1. 容器类型介绍
      • 5.2. 数据容器运算符
        • 5.2.1. 成员运算符
        • 5.2.2. 身份运算符
      • 5.3. 字符串str
        • 5.3.1. 字符串的定义
        • 5.3.2. 运算符的相关操作
        • 5.3.3. 索引和切片
          • 5.3.3.1. 索引
          • 5.3.3.2. 切片
        • 5.3.4. 字符串遍历
        • 5.3.5. 字符串的相关操作
          • 5.3.5.1. 获取的操作 【重要】
          • 5.3.5.2. 转换的操作 【重要】
          • 5.3.5.3. 判断的操作 【重要】
          • 5.3.5.4. 格式化的操作
          • 5.3.5.5. 切割和拼接
          • 5.3.5.6. 替换和移除
      • 5.4. list(列表)
        • 5.4.1. 列表的定义
        • 5.4.2. 列表中的运算符
        • 5.4.3. 索引和切片
        • 5.4.4. 列表的遍历
        • 5.4.5. 列表的操作
        • 5.4.5. 列表推导式
      • 5.5. tuple(元组)
        • 5.5.1. 元组的定义
        • 5.5.2. 元组的运算
        • 5.5.3. 索引和切片
        • 5.5.4. 元组的遍历
        • 5.5.5. 元组的操作
        • 5.5.6. 打包和解包
      • 5.6. set(集合)
        • 5.6.1. 集合的定义
        • 5.6.2. 集合的运算符
        • 5.6.3. 集合的操作【了解】
        • 5.6.4. 不可变集合(frozenset)
      • 5.7. dict(字典、映射)
        • 5.7.1. 字典的定义
        • 5.7.2. 字典的运算符
        • 5.7.3. 字典的操作
        • 5.7.4. 字典的遍历
        • 5.7.5. 字典推导式
      • 5.8. 容器类型总结
      • 5.9. 容器综合案例
        • 双色球

第五章 Python数据容器

5.1. 容器类型介绍

为什么学习数据容器?

思考:需要在程序中记录5名学生的信息,如姓名该如何实现?

# 现有的方式 提供五个变量存储5个学生的姓名
name1 = "张三"
name2 = "李四"
name5 = "王五"
name6 = "赵六"
name7 = "田七"
# 如果现有需求改变,需要记录50个学生的信息,如姓名该如何实现? ---》 还是提供50个变量吗? 是否可行?
# 其实以编程而言是可以的,但是无论是内存空间的开辟,还是后续对数据的使用都很不方便且效率低下

那么,面临数据的批量存储或批量使用该如何操作?就是使用到Python中的容器类型了

name_list = ["张三","李四","王五","赵六","田七"]
#一个变量记录五份数据,这就是数据容器,一个容器可以容纳多份数据,提供对数据存储和操作方式

Python中的数据容器:一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素,每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。

数据容器根据特点的不同如:是否支持重复元素、是否可以修改、是否有序等
数据容器分为5类分别是:字符串(str)、列表(list)、元组(tuple)、集合(set)、字典(dict)

5.2. 数据容器运算符

5.2.1. 成员运算符

针对于容器型数据的,判断一个数据是否为容器中的内部元素

运算符描述
in数据 in 容器型数据 把数据当做一个整体 检查是否在容器型数据中
not in数据 not in 容器型数据 把数据当做一个整体 检查是否不在容器型数据中

5.2.2. 身份运算符

身份运算符用于比较两个对象的内存地址是否一致,是否是对同一对象的引用

运算符描述
idid(数据) 可以获取数据的地址
is数据 is 数据 判断两个数据的地址是否一致
not isnot 数据 is 数据 判断两个数据的地址是否不一致

需要注意:is用于判断两个变量引用对象是否为同一个,而==用于判断引用变量的值是否相等

5.3. 字符串str

字符串是字符的容器:一个字符串可以存放任意数量的字符(包含零个或者多个字符的有序不可变序列)。

需要注意:

  • 不可变:内容一旦确定,就不允许发生变化
  • 有序: 添加顺序和显式顺序一致,元素在添加的时候会为元素设置编号,这个编号是从0开始的【这个编号称为索引、下标、脚标
  • 序列是指:内容连续、有序,可使用下标索引的一类数据容器。列表、元组、字符串,均可以可以视为序列。

5.3.1. 字符串的定义

有两种方式来进行定义:

  1. 使用引号包含格式的字面量定义法
  2. 使用str()进行构造
# 空字字符串
str0 = ''
str0_0 = str()

# 创建字符串
str1 = "我是字符串"
str2 = str("我是字符串")

#str() 不仅可以创建字符串,而且可以将赋值参数转换为字符串类型
str3 = str(10) # "10"
str4 = str([1,2,3,4]) #"[1,2,3,4]"

字符串的分类:

  1. 转义字符串:因为在编程语言中有\,是转义符,会将一些特殊的符号转义成其他的含义

    n ----> \n  换行符
    t ----> \t  水平制表符
    r ----> \r  回车符  【windows系统的字节模式下  换行符是两个符号组成的  \r\n】
    f ----> \f  换页符
    v ----> \v  纵向制表符
    u ----> \u  unicode码的前缀   '\u4e00'
    x ----> \x  字节模式下 十六进制的前缀
    
  2. 原生字符串:保持每个字符原本的含义,就是原生字符串

    对比一下:\n 在转义字符串中是 一个换行符, 原生字符串解读,应该是两个符号反斜杠和n

    将转义字符串转化成原生字符串的方式:

    1. 使用\进行再次转义
  3. 使用r或者R修饰字符串

s = 'C:\\Users\jkMaster\Documents\\test.txt'
print(s)

s = r'C:\Users\jkMaster\Documents\test.txt'
print(s)
# 这两字符串变量打印结果时一样,但是不同点在于,当遇到python中的转移字符串时,如何将转移字符串转变会原有含义的操作即原生字符串的操作

5.3.2. 运算符的相关操作

# +号运算符 提供的是拼接操作(要求:字符串只能和字符串拼接)
print("hello"+" world")

# *号运算符  乘以一个正整数n 将字符串的内容重复n次
print("qfedu "*3)
# %号运算符 格式化在字符串未知的位置使用占位符占位,再对字符串使用%运算符给占位符赋值
#  %s字符串 %d整数	%f小数
print("姓名:%s,年龄%d,薪水%.2f"%("张三",18,1234.56))

# +=号运算符 在变量原来值的基础上拼接上新的内容(要求:字符串只能和字符串拼接)
str1 = "hello"
str1 += " world"
print(str1)

# *=号运算符 在变量值的基础上将内容重复n次 赋值给变量
str2 = "qfedu "
str2 *= 3
print(str2)

# 关系运算符 > >=	< <= ==	!=
# 字符在比较的时候按照什么来比较的???  python是utf-8的编码  所以它是按照utf-8编码规则 对比字符对应的十进制数据
str3_1 = "a"
str3_2 = "A"
print(str3_1 > str3_2)

# 成员运算符
str4_1 = "a"
str4_2 = "abc"
print(f"a是否存在abc中?{str4_1 in str4_2}")
print(f"a是否不存在abc中?{str4_1 not in str4_2}")

#身份运算符
str5_1 = "abc"
str5_2 = "abc"
print(f"str5_1中存储的字符串内存地址是:{id(str5_1)}")
print(f"str5_2中存储的字符串内存地址是:{id(str5_2)}")
print(f"str5_1和str5_2的地址是否相等?:{str5_1 is str5_2}")
print(f"str5_1和str5_2的地址是否不相等?:{not str5_1 is str5_2}")

5.3.3. 索引和切片

5.3.3.1. 索引

索引就是表名字符串中存储字符对应的位置

Python对于序列的索引有两种方式的操作:

  1. 正向索引 【从左向右数】范围是[0, 长度N-1]

  2. 负向索引 【从右向左数】范围是[-1, -N, -1] — 递减数列

对于有序序列来说,想要定位获取或者修改序列中的元素,就需要索引来进行定位,格式: 序列[索引]

# len(序列) --》可以获取序列的长度
s = '\n'
print(len(s))  # 1
s1 = r'\n'
print(len(s1))  # 2

s = r'Welcome to qfedu study'
print(len(s))  # 22

# 获取第一个字符
ch = s[0]  # 定位到之后赋值给变量
print(ch)  # W

# 负向索引
ch = s[-len(s)]
print(ch)  # W

# 获取最后一个字符
last_ch = s[len(s) - 1]
print(last_ch)  # y

last_ch = s[-1]
print(last_ch)  # y


# 获取倒数第三个字符
last_ch_3 = s[-3]
print(last_ch_3)


# 字符串是不允许发生变化【不可变】
# s[0] = 'w'  # 修改这个位置的元素
# TypeError: 'str' object does not support item assignment
# 类型错误:字符串对象不支持元素被指派内容
5.3.3.2. 切片

切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。

通过索引定位范围区域,在这个区域中提取相关的子串信息,切片的操作是序列[起始索引:结束索引:步长]

起始索引和结束索引只是定位范围的,使用正向索引和负向索引均可

根据步长的正负情况切片是分为两种的

  1. 正向切片 【从左向右提取子串】

    步长是为正数,起始索引定位的字符应该在结束索引定位的左边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

  2. 负向切片 【从右向左提取子串】

    步长是负数,起始索引定位的字符应该在结束索引定位的右边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

切片的操作中有些内容是可以省略的:

  1. :步长可以省略,表示步长为1
  2. 起始索引可以省略,如果是正向切片 表示从最左边开始, 如果是负向切片 表示从最右边开始
  3. 结束索引可以省略,如果是正向切片 表示到最右边结束,如果是负向切片 表示到最左边结束
s = r'Welcome to qfedu study'
sub_s = s[0:len(s):1]
print(sub_s)  # Welcome to qfedu study

# 等价于
sub_s = s[:]
print(sub_s) # Welcome to qfedu study

sub_s = s[-1:-len(s)-1:-1]
print(sub_s)  # 对字符串反转
# yduts udefq ot emocleW

# 等价于
sub_s = s[::-1]
print(sub_s)
# tyduts udefq ot emocleW

sub_s = s[:3]  # 提取前3个
print(sub_s)  # Wel


sub_s = s[-3:]  # 提取的是后3个字符
print(sub_s)  # udy

sub_s = s[-3::-1]
print(sub_s)  # uts udefq ot emocleW

sub_s = s[1:-1:-1]
print(sub_s)  # ''

sub_s = s[::2]
print(sub_s)  # Wloet fd td

5.3.4. 字符串遍历

方式1:直接遍历获取元素

for 变量名 in 字符串:
	操作

方式2:使用range生成下标数列,根据下标获取元素

for 变量名 in range(len(字符串)):
	操作

方式3:enumerate枚举遍历序列

对序列操作完成时候 会生成一个新的序列,这个序列中的元素是一个二元组 (下标, 元素)

s = 'nice hello'

for ch in s:
	print(ch)
'''
n
i
c
e
'''
print('=' * 30)

# 因为字符串是有序序列 可以通过索引获取元素
for i in range(len(s)):
	print(i, s[i])

# 获取e这个字符在字符串中的位置
# 直接遍历下标
for i1 in range(len(s)):
	if s[i1] == 'e':
		print(i1)

#  enumerate(s) ---> [(下标, 元素), (下标1, 元素1), (下标2, 元素2)] --》元组的操作在后面会详细说明 这里大家知道如何操作即可
for item in enumerate(s):
	print(item)
'''
(0, 'n')
(1, 'i')
(2, 'c')
(3, 'e')
(4, ' ')
(5, 'h')
(6, 'e')
(7, 'l')
(8, 'l')
(9, 'o')
'''
# 解包: 给多个变量赋值的时候
x, y, z = 10, 11, 12
print(x, y, z)  # 10 11 12
'''
当用逗号分割定义数据时, 解释器会将其解释为一个元组类型
'''
data = 1, 2, 3, 4, 5, 6  # 打包
print(data, type(data))  # (1, 2, 3, 4, 5, 6)  <class 'tuple'>
'''
当把多个数据赋值给多个变量时, 是在给元组数据解包, 将数据赋值给对等位置的变量
'''

for pos, ele in enumerate(s):
	if ele == 'e':
		print(pos)
	

5.3.5. 字符串的相关操作

5.3.5.1. 获取的操作 【重要】
s = r'Welcome to qfedu study'

'''
1. 在指定范围中 查询子串第一次出现的位置
	字符串对象.index(子串, 起始位置, 结束位置)  --- 找不到报错
	字符串对象.find(子串, 起始位置, 结束位置)  --- 找不到 返回的是-1
	
	子串是多个符号 获取的是第一个符号的下标
'''
# 不规定查找范围  从左到右整体查询
pos = s.index('s')
print(pos)
# 对'也有转义的意思  在字符串要展示的内容中 要呈现 '
# 王籽澎的昵称是 '隔壁老王'
message = '王籽澎的昵称是 \'隔壁老王\''
print(message)

# 从指定位置开始进行查找
pos = s.index('s', 3)
print(pos)

# 指定开始与结束[不包含]
#pos = s.index('s', 3, 8)
# print(pos)  # ValueError: substring not found

s1 = 'noodle too'
pos = s1.index('oo')
print(pos)  # 1

pos = s.find('s', 3, 8)
print(pos)  # -1

'''
2. 在指定范围中 查询子串最后一次出现的位置
	字符串对象.rindex(子串, 起始位置, 结束位置)  --- 找不到报错
	字符串对象.rfind(子串, 起始位置, 结束位置)  --- 找不到 返回的是-1

	子串是多个符号 获取的是第一个符号的下标
'''
pos = s.rfind('s')
print(pos)  # 17

pos = s.rfind('s', 0, 10)
print(pos)  # -1


'''
3. 在指定范围中 查询子串出现的次数
	字符串对象.count(子串, 起始位置, 结束位置)
'''
pos = s.count('s')
print(pos)  # 1

# 指定起始 到末尾开始查找
pos = s.count('s', 8)
print(pos)  # 1


pos = s.count('s', 8, len(s))
print(pos)  # 1

5.3.5.2. 转换的操作 【重要】
s = 'helLo,Nice to Meet you.My age is 18.aheklfnfsd hjdhsjhgfs '

# 1. 将小写英文字母转化为大写 其他的不变
new_s = s.upper()
print(new_s)  # HELLO,NICE TO MEET YOU.MY AGE IS 18.
print(s)

# 2. 将大写英文字母转化为小写 其他的不变
new_s = s.lower()
print(new_s)  # hello,nice to meet you.my age is 18.

# 3. 大写转小写 小写转大写 其他字符不变
new_s = s.swapcase()
print(new_s)  # HELLO,nICE TO mEET YOU.mY AGE IS 18.

# 4. 首字母大写 其他字母小写  其他符号不变
new_s = s.capitalize()
print(new_s)  # Hello,nice to meet you.my age is 18.

# 5. 每个单词首字母大写 其他小写
# 单词: 非连续性的符号组在一起就是单词
new_s = s.title()
print(new_s)  # Hello,Nice To Meet You.My Age Is 18.Aheklfnfsd Hjdhsjhgfs

# 6. 根据编码规则 获取字符对应的字节数据
print(hex(255))  # 0xff
'''
GBK编码  一个汉字2个字节   1个字节是8位
UTF-8编码 一个汉字是3个字节
 二进制数据位数比较多 可读性差一些  所以展示字节数据的时候 使用的十六进制的格式
 
 单字节数据 【ASCII】 --- 编码之前和编码之后的形态是一样的
'''
s = 'abc1234你好'
# 按照GBK的编码规则 获取字符对应的字节数据
byte_data = s.encode(encoding='gbk')
print(byte_data)  # b'abc1234\xc4\xe3\xba\xc3'   字节串

# 字节串的内容就是 字节数据 [呈现的时候转化为十进制数据了]
for b in byte_data:
	print(b)
'''
97
98
99
49
50
51
52
196
227
186
195
'''

# 解码: 将字节数据按照编码规则 解析成字符串
s1 = byte_data.decode(encoding='gbk')  # 编码规则和解码规则要保持一致   如果不一致 要么报错 要么乱码
print(s1)  # abc1234你好


s2 = '你好啊'
byte_data1 = s2.encode(encoding='utf-8')
print(byte_data1)  # b'\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x95\x8a'

# s3 = byte_data1.decode(encoding='gbk')
# print(s3)  # UnicodeDecodeError: 'gbk' codec can't decode byte 0x8a in position 8: incomplete multibyte sequence

s4 = '你好'
byte_data2 = s4.encode(encoding='utf-8')
print(byte_data2)  # b'\xe4\xbd\xa0\xe5\xa5\xbd'

s5 = byte_data2.decode(encoding='gbk')
print(s5)  # 浣犲ソ

5.3.5.3. 判断的操作 【重要】
# 1. 判断字符串的内容是否为纯数字
s = '1230'
res = s.isdigit()
print(res)  # True

s = '1230 '
print(s.isdigit())  # False

# 2. 判断字符串的内容是否为纯字母
# 字母:世界各国语言 统称为字母
s = 'abc你Вㅘタ'
res = s.isalpha()
print(res)  # True

# 要判断是否为纯英文字母 【英文是单字节数据特点】
'''
单字节和多字节的特点是编码之后 的字节串的内容不一样
单字节保持不变 【不会出现其他的符号】
多字节会按照字节数转成十六进制的数据 【例如\xaf】  就会出现非字母的符号
'''
s1 = 'abc'
s2 = 'abc你'
print(s1.encode(encoding='utf-8'))  # b'abc'
print(s2.encode(encoding='utf-8'))  # b'abc\xe4\xbd\xa0'

# 要判断是否为纯英文字母
print(s1.encode('utf-8').isalpha())  # True
print(s2.encode('utf-8').isalpha())  # False

# 3. 判断字符串的内容是否为数字或者字母  [纯数字  纯字母  数字和字母]
print('123'.isalnum()) # True
print('123abc'.isalnum())  # True
print('123abc比你好'.isalnum())  # True
print('123abc你好 hello'.isalnum())  # False

# 如何判断字符串的内容为数字或者英文字母  【同上】
print('123abc'.encode(encoding='utf-8').isalnum())  # True
print('123abc比你好'.encode(encoding='utf-8').isalnum())  # False

# 如何判断字符串的内容为数字和英文字母  【既有数字 又有英文字母】
s = '123'
res = s.encode(encoding='utf-8').isalnum() is True and s.isdigit() is False and s.encode(encoding='utf-8').isalpha() is False
print(res)

# 4. 判断字符串中的英文字母是否为大写字母
s = 'her12324'
res = s.isupper()
print(res)  # False

s1 = 'HER12324'
res = s1.isupper()
print(res)  # True

# 5. 判断字符串中的英文字母是否为小写字母
res = s.islower()
print(res)  # True
res = s1.islower()
print(res)  # False

# 6. 判断字符串的内容是否满足 单词的首字母大写 其他小写
s = 'Good Nice 13'
res = s.istitle()
print(res)  # True

s1 = 'Good nice 13'
res = s1.istitle()
print(res)  # False

# 7. 判断字符串的内容是否是ASCII码符号
print(s.isascii())  # True

# 8. 判断字符串的内容是否已指定内容开头
# res = 'good good study'.startswith(指定内容)
'''
指定内容的数据类型:
	1. 字符串  验证是否以指定的字符串开头
	2. (字符串1,字符串2, 字符串3)  元组类型的数据   判断字符串的内容是否以其中一个开头
'''
res = 'good good study'.startswith('good')
print(res)  # True

res = 'Good good study'.startswith('good')
print(res)  # False

res = 'Good good study'.startswith(('good', 'Good', 'GOOD'))
print(res)  # True

# 9. 判断字符串的内容是否已指定内容结尾
'''
1. 字符串  验证是否以指定的字符串结尾
2. (字符串1,字符串2, 字符串3)  元组类型的数据   判断字符串的内容是否以其中一个结尾
'''
res = 'good good study'.endswith('dy')
print(res)

res = 'good good stuDy'.endswith(('dy', 'Dy', 'DY', 'dY'))
print(res)
5.3.5.4. 格式化的操作
# 1. 按照指定宽度 对展示的字符串内容填充数据 【居左右填充  居右左填充  居中左右填充】
s = 'hello'
print(s)
# 居左右填充
# new_s = s.ljust(宽度, 填充符)  # 填充符默认是空格
new_s = s.ljust(10)
print(new_s)   # 'hello     '

new_s = s.ljust(10, '-')
print(new_s)  # hello-----

# 居右左填充
new_s = s.rjust(10)
print(new_s)  # '     hello'
new_s = s.rjust(10, '*')
print(new_s)  # '*****hello'

# 居中
new_s = s.center(10)
print(new_s)  # '  hello   '
new_s = s.center(10, '+')
print(new_s)  # '++hello+++'

# 2. 按照指定宽度 对字符串进行右对齐 左边填充0
s = '10'
new_s = s.zfill(10)
print(new_s)  # 0000000010

# 3. 引号嵌套的问题***  【展示的内容中有双引号  字符串数据就采用单引号包含 】
# 展示的内容中有单引号  字符串数据就采用双引号包含
s = "王籽澎的昵称是 '隔壁老王'"
print(s)

s = '王籽澎的昵称是 "隔壁老王"'
print(s)

# 有冲突的情况 内外引号情况一样 解决方式就是对内部引号采用转义符转义  取消掉字符串标记的含义
s = '王籽澎的昵称是 \'隔壁老王\''
print(s)

# 4. 字符串内容比较长 *** 可以直接换行写多个字符串 会自动拼接在一起  使用\把多个字符串连接在一起  形成一个
s = '其中五六只虾已熟透发红。方女士称,当天气温41度,' \
	'可能是自己把虾往地上和电动车后座放了的缘故,温度太高虾被烫熟了,' \
	'觉得十分搞笑。感慨这天气能不出门就不出门,待在空调房里最香。'
print(s)

s = '其中五六只虾已熟透发红。方女士称,当天气温41度,可能是自己把虾往地上和电动车后座放了的缘故,温度太高虾被烫熟了,觉得十分搞笑。感慨这天气能不出门就不出门,待在空调房里最香。'
print(s)

# 5. 字符串格式化
'''
除了%运算符之外  字符串也提供了相应的操作

字符串对象.format(填充的数据)
这种格式化方式,字符串对象里面的未知数据的占位符采用的是{}
'''
name = '王籽澎'
gender = '男'
age = 21
score = 79.9
message = '这个人叫%s, 今年%d岁 性别是%s  成绩是%f' % (name, age, gender, score)
print(message)

message = '这个人叫{}, 今年{}岁 性别是{}  成绩是{:.2f}'.format(name, age, gender, score)
print(message)

''' *******
Python3.6出现了简化操作  使用f或者F修饰字符串  在需要填充数据的地方 直接 {数据}
如何对数据进一步格式化
	保留多少位小数 {数据:.nf}  n保留小数的位数
	按照指定宽度填充数据 {数据:[占位符][对齐模式][宽度]}
		占位符默认是空格
		对齐模式 >[居右]  ^[居中]  <[居左]
	千位分割法 {数据:,}
'''
message = f'这个人叫{name}, 今年{age}岁 性别是{gender} 成绩是{score:.2f}  学号{10:0>6} 千位分割{12345678987654567:,}' \
	f'二进制展示数据{10:0b}  八进制展示数据{10:0o}  十六进制{10:0x} ' \
	f'科学计数法{123456789234567:e}'

print(message)

value = input('请输入数据:')
# 打印出来的信息是 value=数据值
info = f'{value=}'  # 3.8中新增的
print(info)  # value='19'


5.3.5.5. 切割和拼接
# 切割: 以指定子串为切割点 将字符串分成n段
'''
字符串数据.split(切割符, 切割次数)  没有设置切割次数 能切几次切几次
	从左开始查找切割点 进行切割的

字符串数据.rsplit(切割符, 切割次数)  没有设置切割次数 能切几次切几次
	从右开始查找切割点 进行切割的
'''
s = 'hello nice   to meet you'
# 以 'e'为切割点
sub_list = s.split('e')
print(sub_list)  # ['h', 'llo nic', '   to m', '', 't you']
'''
'h'
'llo nic'
'   to m'
''
't you'
'''
# 如果没有设置切割符  默认以任意的空白符号为切割符  会将结果中的空字符串给移除
'''
空格
换行
制表符等等
'''
sub_list = s.split()
print(sub_list)  # ['hello', 'nice', 'to', 'meet', 'you']

# 设置切割次数
sub_list = s.split('e', 1)
print(sub_list)  # ['h', 'llo nice   to meet you']


sub_list = s.rsplit('e')
print(sub_list)  # ['h', 'llo nic', '   to m', '', 't you']

sub_list = s.rsplit('e', 1)
print(sub_list)  # ['hello nice   to me', 't you']


# 2. 拼接
# 使用拼接符把序列中的内容拼接成一个字符串
'''
'拼接符'.join(序列)
	底层实现就是采用的+号拼接  【字符串只能跟字符串拼接】
	序列中的元素必须是字符串类型的
	
'''
words = ['hello', 'nice', 'to', 'meet', 'you']
res = '_'.join(words)
print(res)  # hello_nice_to_meet_you

# nums = (11, 23, 45)
# res = '+'.join(nums)  # TypeError: sequence item 0: expected str instance, int found
5.3.5.6. 替换和移除
# 替换
'''
字符串数据.replace(旧子串, 新子串, 个数)
	旧子串 --- 要替换掉的
	新子串 --- 要替换成的
	个数 --- 不设置的换 默认全部替换
'''
s = 'good good god'
new_s = s.replace('g', 'G')
print(new_s)  # Good Good God

new_s = s.replace('g', 'G', 1)
print(new_s)  # Good good god

new_s = s.replace(' ', '_')
print(new_s)  # good_good_god

'''
移除的是两端的内容
	字符串数据.strip(指定内容)  移除字符串两端的指定内容
	字符串数据.lstrip(指定内容) 只移除左端的指定内容
	字符串数据.rstrip(指定内容) 只移除右端的指定内容

指定内容没有设置 移除的是任意的空白符号
'''
s = ' \t\r\nabc\tgood \n'
new_s= s.strip()
print(new_s)  # abc	good

s = '@#$%^abc\tgood^%$#'
new_s = s.strip('@#$%^&*')  # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s)  # abc	good

s = '@#$%^abc\tgood^%$#'
new_s = s.lstrip('@#$%^&*')  # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s)  # abc	good^%$#

s = '@#$%^abc\tgood^%$#'
new_s = s.rstrip('@#$%^&*')  # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s)  # @#$%^abc	good

总结:

作为数据容器,字符串有如下特点:只可以存储字符串、长度任意(取决于内存大小)、支持下标索引、允许重复字符串存在、不可以修改(增加或删除元素等)、支持for循环

5.4. list(列表)

概念:存放零个或者多个数据的有序的可变的序列

列表数据的标识是[],是在[]存储元素,元素之间使用,隔开

列表中是可以存放不同类型的数据作为元素的,但是为了数据的统一性,所以我们一般来存储的时候类型就是统一的

5.4.1. 列表的定义

  1. 采用[]字面量定义法
  2. 采用list()构造
l0 = []  # 空列表
print(l0)  # []

l1 = [19, 28, 44, 56, 38]
print(l1)

# list()构造
l2 = list()
print(l2)  # []

# 把其他序列类型转化为列表类型 【构造一个列表 把其他序列中的元素添加在列表中】
l3 = list('10')
print(l3)  # ['1', '0']

l4 = list(range(1, 100, 10))
print(l4)  # [1, 11, 21, 31, 41, 51, 61, 71, 81, 91]

5.4.2. 列表中的运算符

l1 = [19, 27, 83, 56]
l2 = [77, 55, 43]
# +	合并两个列表中的数据 把数据添加到一个新的列表中
new_li = l1 + l2
print(new_li)  # [19, 27, 83, 56, 77, 55, 43]

# *  将列表中的元素重复n次 放在一个新的列表中
new_li = l1 * 3
print(new_li, l1)  # [19, 27, 83, 56, 19, 27, 83, 56, 19, 27, 83, 56]

# +=  将当前列表的基础上追加其他序列中的元素
l1 += range(1, 10)
print(l1)  # [19, 27, 83, 56, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# *=  将当前列表的元素重复n次
l1 *= 2
print(l1)  # [19, 27, 83, 56, 1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 27, 83, 56, 1, 2, 3, 4, 5, 6, 7, 8, 9]

#比较运算符【> >=	< <= ==	!=】相同位置的元素进行比较  直到产生结果 比较结束
l3 = ['good', 'nice']
l4 = ['god', 'look']
print(l3 > l4)  # True  --》 good 和 god  比较

# 成员运算符 in 和 not in 判断元素是否在或者不在列表中
print(19 in l1)  # True
print(19 not in l1) # False

# 身份运算符 id 、is 和 not is
print(id(l1)) # 获取地址
print(id(l2)) # 获取地址
print(l1 is l2) # 判断地址是否一致
print(not l1 is l2)# 判断地址是否不一致

5.4.3. 索引和切片

索引

python索引分为正向索引和负向索引

  • 正向索引的范围是[0, 长度N - 1] 从左向右

  • 负向索引的范围是[-1, -长度N] 从右向左

通过索引定位到对应位置,修改或者获取该位置的元素

nums = [19, 27, 38, 41, 25]

# 获取第2个元素
ele = nums[1]
print(ele)

# 获取倒数第二个
ele = nums[-2]
print(ele)

# 修改
nums[0] = 87
print(nums)  # [87, 27, 38, 41, 25]

nums[-1] = 65
print(nums)  # [87, 27, 38, 41, 65]

切片

切片类似于字符串 列表[start:stop:step]

  • 正向切片步长step为正数 表示从左向右取值

  • 负向切片步长step为负数 表示从右向左取值

start和stop只是来定位取数据的范围

  • start省略 正向切片的时候 表示从最左边开始 负向切片表示从最右边开始

  • stop省略 正向切片的时候 表示到最右边结束 负向切片表示到最左边结束

# 切片
sun_nums = nums[::2]
print(sun_nums)  # [87, 38, 65]

sun_nums = nums[::-1]
print(sun_nums)  # [65, 41, 38, 27, 87]

sun_nums = nums[:]
print(sun_nums)  # [87, 27, 38, 41, 65]  备份了一份

'''
切片:根据索引以及步长定位到列表的多个位置
因为列表是可变的  也可以通过切片对这些位置的数据进行修改  【赋值得是一个序列型数据】
切片定位的下标范围是连续的  赋值的个数可以随便
但是位置是跳跃的  定位到几个位置  就得赋予几个值
'''
nums[:2] = [19, 33]
print(nums)  # [19, 33, 38, 41, 65]
nums[:2] = [19]
print(nums)  # [19, 38, 41, 65]
nums[:2] = [19, 99, 78, 36]
print(nums)  # [19, 99, 78, 36, 41, 65]

# nums[::2] = [99]
# print(nums)  # ValueError: attempt to assign sequence of size 1 to extended slice of size 3

nums[::2] = [99] * 3
print(nums)  # [99, 99, 99, 36, 99, 65]

5.4.4. 列表的遍历

方式1:直接遍历获取元素

for 变量名 in 列表:
	操作

方式2:使用range生成下标数列,根据下标获取元素

for 变量名 in range(len(列表)):
	操作

方式3:enumerate枚举遍历序列

对序列操作完成时候 会生成一个新的序列,这个序列中的元素是一个二元组 (下标, 元素)

# 直接遍历元素
words = ['hello', 'enumerate', 'length', 'operator', 'expression', 'sort']
for w in words:
	print(w)

# 过滤  要获取长度在6以上的单词
'''
肯定要接收结果的,由于结果是有多个的 肯定得定义一个容器来接收
1. 定义一个空列表
2. 遍历列表
3. 按照需求判断 找到符合要求的数据 把数据添加在列表中
	+=  在当前列表的基础上 追加其他序列中的元素
'''
greatest_6 = []
# 遍历
for w1 in words:
	if len(w1) > 6:
		# greatest_6 += [w1]  # 加上中括号的原因 是因为得把w1当做整体数据  追加在greatest_6中  w1得放在一个序列中
		# append
		greatest_6.append(w1)  # 列表中提供的追加元素的操作
print(greatest_6)


# 转换  把列表中的每个单词 转换成首字母大写 其他字母小写
new_words = []
for w2 in words:
	new_words.append(w2.title())
print(new_words)
# ['Hello', 'Enumerate', 'Length', 'Operator', 'Expression', 'Sort']


nums = [18, 29, 33, 56]
# 将nums中元素 通过+拼接在一起
str_nums = []
for ele in nums:
	str_nums.append(str(ele))
print(str_nums)  # ['18', '29', '33', '56']

res = '+'.join(str_nums)
print(res)  # 18+29+33+56



nums1 = [77, 56, 39, 28, 41, 63, 55]
# 质数【在大于1的自然数中 只有1和本身这两个因数的数据为质数】
'''
在2到本身-1之间不存在因数  这种数是质数
'''
# 找到nums1中质数的下标  【列表是可以通过下标定位到元素的】
for i in range(len(nums1)):
	# print(nums1[i])  # 判断nums1[i]是不是质数
	# 设置一个标记 假设是
	flag = True
	# 遍历获取2-本身-1之间的数据
	for v in range(2, int(nums1[i] ** 0.5) + 1):
		if nums1[i] % v == 0:
			# 这里就找到了1和本身之外的因数了
			flag = False
			break
	# 结束验证 看一下flag标记的值
	# 假设没有被推到 假设成立 这个数据就是质数
	if flag is True:
		print(i)
		
	

for pos, ele1 in enumerate(nums1):
	# 设置一个标记 假设ele1持有的数据是质数
	flag = True
	# 遍历获取2-本身-1之间的数据
	for v in range(2, int(ele1 ** 0.5) + 1):
		if ele1 % v == 0:
			# 这里就找到了1和本身之外的因数了
			flag = False
			break
	# 结束验证 看一下flag标记的值
	# 假设没有被推到 假设成立 这个数据就是质数
	if flag is True:
		print(pos)
	

5.4.5. 列表的操作

nums = [23, 71, 29, 77, 83, 23, 14, 51, 79, 23]

# 1. 添加数据的操作
# 在末尾追加数据
res = nums.append(17)
print(res)  # None  列表是一个可变的数据 相关操作没有产生新的内容 影响的都是原数据  所以拿到的是None
print(nums)  # 看操作有没有影响  看原数据
# [23, 71, 29, 77, 83, 23, 14, 51, 79, 23, 17]

# 在指定下标的位置添加数据  该位置及其之后的数据会向后移动一位
nums.insert(1, 80)
print(nums)  # [23, 80, 71, 29, 77, 83, 23, 14, 51, 79, 23, 17]
nums.insert(-2, 77)
print(nums)  # [23, 80, 71, 29, 77, 83, 23, 14, 51, 79, 77, 23, 17]

# 合并其他序列的元素   等同于+=
nums.extend(range(7, 100, 7))
print(nums)
# [23, 80, 71, 29, 77, 83, 23, 14, 51, 79, 77, 23, 17, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]

# 2. 删除的操作
# 删除末尾的元素  返回的是被删掉的数据
value = nums.pop()
print(value)  # 98
print(nums)  # [23, 80, 71, 29, 77, 83, 23, 14, 51, 79, 77, 23, 17, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91]

# 删除指定索引位置的元素   【删除该位置的元素 后面的元素会补位】
value = nums.pop(1)
print(nums, value)
# [23, 71, 29, 77, 83, 23, 14, 51, 79, 77, 23, 17, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91] 80

# 删除指定元素  【如果没有这个元素 会报错  如果这个元素是重复的 删除是查找到第一个】
# nums.remove(99)  # ValueError: list.remove(x): x not in list

nums.remove(23)
print(nums)
# [71, 29, 77, 83, 23, 14, 51, 79, 77, 23, 17, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91]

# 清空列表
# nums.clear()
# print(nums)  # []

# 3. 获取相关的操作
# 3.1 获取元素在指定的范围内第一个出现的位置
'''
列表数据.index(数据, 起始位置, 结束位置)
如果找不到 报错
'''
pos = nums.index(23)
print(pos)  # 4

pos = nums.index(23, 5)
print(pos)  # 9

# pos = nums.index(23, 5, 9)
# print(pos)  # ValueError: 23 is not in list

# 3.2 获取元素在列表中出现的次数
'''
列表数据.count(数据)
'''
count = nums.count(23)
print(count)  # 2

# 3.3 获取列表中元素的最大值
'''
max(序列) --- 获取序列中最大的元素

打包这个名词  多个数据用逗号分开 会把数据打包成元组
'''
print(max(nums))  # 91
print(max('good'))  # o
# 获取多个数据中的最大值 最小值
print(max(19, 34, 56, 72, 38))  # 72

# 3.4 获取列表中元素的最小值
'''
min(序列) --- 获取序列中最小的元素
'''
print(min(nums))  # 7
print(min(19, 34, 56, 72, 38))  # 19

# 4.其他的操作
# 4.1拷贝列表
copy_nums = nums.copy()
print(copy_nums)
print(id(nums), id(copy_nums))

# 4.2 对列表的元素按照大小进行排序
# nums.sort()  # 升序排序
# print(nums)
# # [7, 14, 14, 17, 21, 23, 23, 28, 29, 35, 42, 49, 51, 56, 63, 70, 71, 77, 77, 77, 79, 83, 84, 91]

# nums.sort(reverse=True)  # 升序之后是否反转  是的话 就变成降序了 默认是False
# print(nums)
# [91, 84, 83, 79, 77, 77, 77, 71, 70, 63, 56, 51, 49, 42, 35, 29, 28, 23, 23, 21, 17, 14, 14, 7]

# 4.3 对列表的内容进行反转
'''
和切片反转的区别:
	切片反转生成是新的列表
	而这个操作是影响的原列表
'''
new_nums = nums[::-1]
print(new_nums)
print(id(new_nums), id(nums))
nums.reverse()
print(nums)

5.4.5. 列表推导式

理解成对列表过滤或者转换格式的简化,虽然说是简化,但是它要比append操作效率要高

对数据进行过滤 [变量 for 变量 in 序列 if 判断条件]

对数据进行转换 [对变量转换之后数据 for 变量 in 序列]

'''
2. 已知一个数字列表`nums = [1, 2, 3, 4, 5]`, 编写程序将列表中所有元素乘以2
'''
nums = [1, 2, 3, 4, 5]
pow_nums = []
for ele in nums:
	pow_nums.append(ele * 2)
print(pow_nums)  # [2, 4, 6, 8, 10]

# 列表推导式
new_nums = [ele * 2 for ele in nums]
print(new_nums)

nums = [19, 23, 45, 67]
# 用+号把数据拼在一起   使用的是字符串的join
res = '+'.join([str(ele) for ele in nums])
print(res)
'''
3. 列表中存储学生的成绩`scores = [98, 67, 56, 77, 45, 81, 54]`,去除掉不及格的成绩
'''
scores = [98, 67, 56, 77, 45, 81, 54]
# 保留及格
pass_scores = []
for sc in scores:
	if sc >= 60:
		pass_scores.append(sc)
print(pass_scores)

# 列表推导式
pass_scores1 = [sc for sc in scores if sc >= 60]
print(pass_scores1)

'''
1. `There is no denying that successful business lies in a healthy body and mind`提取这句话中包含`i`的**单词**
'''
s = 'There is no denying that successful business lies in a healthy body and mind'
# 切割
words = s.split()
print(words)
i_words = [w for w in words if 'i' in w]
print(i_words)
'''
5. `names = ['lucy', 'lulu', 'john', 'rose', 'hanmeimei', 'lili', 'rosum']`
   1. 查找列表中包含`o`的名字
   2. 查找列表中以`r`开头的名字
   3. 查找列表中长度在4个以上的名字
'''
names = ['lucy', 'lulu', 'john', 'rose', 'hanmeimei', 'lili', 'rosum']
o_names = [name for name in names if 'o' in name]
r_names = [name for name in names if name.startswith('r')]
greatest_4_names = [name for name in names if len(name) > 4]
print(o_names, r_names, greatest_4_names)

总结:

列表:可以容纳多个元素(上限为2**63-1、9223372036854775807个)、可以容纳不同类型的元素(混装)、数据是有序存储的(有下标序号)、允许重复数据存在、可以修改(增加或删除元素等)

5.5. tuple(元组)

元组和列表类似,与列表的区别是列表是可变的【元素的值可以更改,长度可以发生变化】,

元组是不可变

元组的数据标记是() 【提高表达式优先级也是使用()包含的】

有些场景下存储的数据是固定的,像这种情况建议使用元组。【从内存角度来说 使用元组会比列表少占内存】

5.5.1. 元组的定义

元组有几个元素就称为几元组

  1. 使用()字面量形式来定义
  2. 使用tuple()来构造
# 1. 元组的定义
t = ()  # 空元组
print(t, type(t))  # ()  <class 'tuple'>

# 当元组中只有一个数据时 元素后面必须加上逗号 【不加的话 解释器把它解释成提高表达式优先级的意思了】
t1 = (10)
print(type(t1), t1)  # <class 'int'> 10

t2 = (10,)  # 定义一元组的注意事项
print(type(t2), t2)  # <class 'tuple'> (10,)

t3 = (12, 34, 56, 78)
print(t3)

# 用tuple构造 【把其他序列转换为元组类型】
t0 = tuple()  # 空元组
print(t0)  # ()

t1 = tuple('hello')
print(t1)  # ('h', 'e', 'l', 'l', 'o')('h', 'e', 'l', 'l', 'o')

5.5.2. 元组的运算

"""
+  合并  放在一个新的元组中
*  重复
+=  在当前元组的数据的基础上 合并新的序列  但是生成一个新的元组
*=   在当前元组的数据的基础上 完成重复  但是生成一个新的元组
比较运算符 > >=  <  <=  ==  !=相同索引位置的元素进行比较  直到结果的出现
成员运算符 in  和 not in
身份运算符 id 、is 和 not is
"""
t1 = (1, 2, 3)
t2 = (5, 6, 7)
print(id(t1))  # 2245004633920
new_t = t1 + t2
print(new_t, t1, t2)

t1 += (8, 9)
print(t1, id(t1))  # (1, 2, 3, 8, 9)  2245045930640

t2 = (10,20) * 3
print(t2)

5.5.3. 索引和切片

元组的索引和切片操作更类同于字符串,因为是不可变的 只有获取没有修改

索引

Python对于序列的索引有两种方式的操作:

  1. 正向索引 【从左向右数】范围是[0, 长度N-1]

  2. 负向索引 【从右向左数】范围是[-1, -N, -1] — 递减数列

对于有序序列来说,想要定位获取或者修改序列中的元素,就需要索引来进行定位,格式: 序列[索引]

切片

通过索引定位范围区域,在这个区域中提取相关的子串信息,切片的操作是序列[起始索引:结束索引:步长]

起始索引和结束索引只是定位范围的,使用正向索引和负向索引均可

根据步长的正负情况切片是分为两种的

  1. 正向切片 【从左向右提取子串】

    步长是为正数,起始索引定位的字符应该在结束索引定位的左边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

  2. 负向切片 【从右向左提取子串】

    步长是负数,起始索引定位的字符应该在结束索引定位的右边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

切片的操作中有些内容是可以省略的:

  1. :步长可以省略,表示步长为1
  2. 起始索引可以省略,如果是正向切片 表示从最左边开始, 如果是负向切片 表示从最右边开始
  3. 结束索引可以省略,如果是正向切片 表示到最右边结束,如果是负向切片 表示到最左边结束
t = (13, 45, 67, 8, 29, 33, 56, 71)

# 获取倒数第3个元素
print(t[-3])
# 获取前3个
print(t[:3])  # (13, 45, 67)

# 反转
print(t[::-1])

5.5.4. 元组的遍历

方式1:直接遍历获取元素

for 变量名 in 元组:
	操作

方式2:使用range生成下标数列,根据下标获取元素

for 变量名 in range(len(元组)):
	操作

方式3:enumerate枚举遍历序列

对序列操作完成时候 会生成一个新的序列,这个序列中的元素是一个二元组 (下标, 元素)

# 遍历
for ele in t:
	print(ele)

for i in range(len(t)):
	print(t[i])

for i, ele in enumerate(t):
	print(i, ele)

5.5.5. 元组的操作

t = (28, 34, 56, 78, 19, 23, 45, 67, 19)

print(len(t)) # 元组的长度

print(t.index(19))  # 获取元素第一次出现的位置

print(t.index(19, 5))  # 从下标5开始第一次出现的位置

# 在区间[5,8)之间第一次出现的位置
# print(t.index(19, 5, 8))  # ValueError: tuple.index(x): x not in tuple

# 统计某个元素出现的次数
print(t.count(19))  # 2

5.5.6. 打包和解包

打包:当我们使用逗号分割定义多个数据,赋值给一个变量时, 会将数据打包成元组,赋值给该变量

解包:把序列中的元素赋值给多个变量时,把序列解包,将相同位置的数据赋值给对应位置的变量

# 打包
a = 10, 22, 33, 45, 61
print(type(a), a)  # <class 'tuple'>  (10, 22, 33, 45, 61)

# 解包
a, b, c = 'xyz'
print(a, b, c)  # 'x'  'y'  'z'

m, n = [11, 27]
print(m, n)  # 11 27

p, q, k = range(3)
print(p, q, k)  # 0 1 2

需要注意:

当变量的个数与序列中元素个数不对等时,会出现问题报错的

# h, i, j = [19, 22]
# ValueError: not enough values to unpack (expected 3, got 2)

# h, i, j, l, e = [19, 22, 33, 56, 71, 89]
# ValueError: too many values to unpack (expected 5)

# h, i, j, l, e, *t = [19, 22, 33, 56, 71, 89, 78, 65]
# print(h, i,j, l, e, t )  # 19 22 33 56 71 [89, 78, 65]


# *t, h, i, j, l, e = [19, 22, 33, 56, 71, 89, 78, 65]
# print(h, i,j, l, e, t )  # 56 71 89 78 65 [19, 22, 33]

h, i, *t, j, l, e = [19, 22, 33, 56, 71, 89, 78, 65]
print(h, i,j, l, e, t )  # 19 22 89 78 65 [33, 56, 71]

这个错误可以使用星号表达式来解决 , 用*修饰一个变量名,用它去接受过多的数据,因为*修饰完成之后将其变量容器型数据,可以来接受多个数据

总结:

元组:可以容纳多个数据、可以容纳不同类型的数据(混装)、数据是有序存储的(下标索引)、允许重复数据存在、不可以修改(增加或删除元素等)、支持for循环、多数特性和list一致,不同点在于不可修改的特性。

5.6. set(集合)

由一个或多个确定的元素所构成的整体,称为集合,集合中的东西称为元素

集合的特点是 :

  1. 确定性 【要么在集合中 要么不在】
  2. 唯一性 【集合中的元素是唯一的 不重复的】
  3. 无序性

集合是可变的无序序列

5.6.1. 集合的定义

  1. 使用字面量{}定义法 【不能定义空集合】
  2. 使用set()进行构造
# 1. 字面量方式
s = {18, 27, 33, 56, 41}
print(type(s), s)  # <class 'set'> {33, 41, 18, 56, 27}

# 2. set构造
# 定义空集合的唯一方式
s0 = set()
print(s0)  # set()

# 将其他序列转换成集合  顺便对元素去重
s1 = set('hello')
print(s1)  # {'l', 'h', 'e', 'o'}

5.6.2. 集合的运算符

"""
&   交集 把数据存储在一个新的集合中
|   并集 把数据存储在一个新的集合中
^   对称差 把数据存储在一个新的集合中
-   差集 把数据存储在一个新的集合中

&= 交集  修改前者
|= 并集  修改前者
^= 对称差  修改前者
-= 差集  修改前者

>   判断后者是否为前者的真子集
>=  判断后者是否为前者的子集
<   判断前者是否为后者的真子集
<=  判断前者是否为后者的子集
==  判断两个集合数据是否一样
!=  判断两个集合数据是否不一样

in  判断元素是否包含在集合中
not in  判断元素是否不包含在集合中
id 获取地址
is 判断地址是否一致
not is 判断地址是否不止一致
"""
s1 = {19, 22, 38, 41, 56, 27}
s2 = {22, 41, 56, 33, 29, 45}

# 交集
new_s = s1 & s2
print(new_s, s1, s2)
# {56, 41, 22} {38, 41, 19, 22, 56, 27} {33, 41, 45, 22, 56, 29}

# 并集
new_s = s1 | s2
print(new_s, s1, s2)
# {33, 38, 41, 45, 19, 22, 56, 27, 29} {38, 41, 19, 22, 56, 27} {33, 41, 45, 22, 56, 29}

# 差集
new_s = s1 - s2
print(new_s, s1, s2)
# {27, 19, 38} {38, 41, 19, 22, 56, 27} {33, 41, 45, 22, 56, 29}

# 对称差
new_s = s1 ^ s2   # 并集 - 交集
print(new_s, s1, s2)
# {33, 38, 45, 19, 27, 29} {38, 41, 19, 22, 56, 27} {33, 41, 45, 22, 56, 29}

s1 &= s2
print(s1, s2)  # {56, 41, 22} {33, 41, 45, 22, 56, 29}


# 判断的操作
s3 = {19, 22, 45, 67, 82}

print(s3 > {22, 45, 67, 19, 82})  # False

print(s3 >= {22, 45, 67, 19, 82})  # True

print({67, 22} < s3)  # True

print(s3 == {22, 45, 67, 19, 82})  # True

print(s3 != {22, 45, 67, 19, 82})  # False


print(19 in s3)  # True

5.6.3. 集合的操作【了解】

有一些操作与集合的运算符是对应的

s1 = {13, 27, 38}

# 添加元素
s1.add(38)
print(s1)  # 元素存在 不做响应
s1.add(19)
print(s1)  # {19, 27, 13, 38}

# 移除
s1.remove(27)  # 不是成员 会报错
print(s1)
s1.discard(27)  # 不是成员 不做响应
print(s1)
# s1.clear()  # 清空

# 拷贝集合
s2 = s1.copy()
print(s2)

# 判断两个集合是否不存在交集
print({12, 34}.isdisjoint({77, 82}))  # True

print({12, 34}.isdisjoint({77, 82, 12}))  # False

# 因为集合没有索引,所以只能使用追简单的for循环操作
for ele in s1:
    print(ele)

5.6.4. 不可变集合(frozenset)

frozensetset的关系 和 tuplelist的关系差不多

# 构造定义不可变集合 【把其他序列转变成不可变集合】
fs = frozenset({12, 34, 56, 7})
print(fs)

fs1 = frozenset([33, 56, 27, 15])
print(fs1)

print(fs & fs1)  # frozenset({56})

总结:

集合:可以容纳多个数据、可以容纳不同类型的数据(混装)、数据是无序存储的(不支持下标索引)、不允许重复数据存在、可以修改(增加或删除元素等)、支持for循环

5.7. dict(字典、映射)

类似于新华字典的结构,里面的数据放的是成对的数据,这个数据叫做键值对

这个键类似于新华字典中要查的词,值就类似于这个词对应的解释

在新华字典中需要先定位到字,才能查到相应的解释

Python中字典的结构是一样的,是根据键定位到值的。所以对键是有要求的:

  1. 不允许重复
  2. 不允许发生变化 【键对应的类型必须是不可变的 --整数 字符串 元组】

字典的数据结构本质是无序的可变序列 【在Python3.6的时候做了一个优化,字典的从内存角度来说比3.5及其之前的降低25%, 展示的时候跟书写的时候 顺序是一致的】

无序的数据就没有编号【索引】这一说。字典中定位数据就通过键来定位的,字典的键就等同于有序数据的索引

5.7.1. 字典的定义

  1. 通过{}字面量法来定义,存在键值对的时候,结构是 {key: value, key1: value1}
  2. 通过dict()来进行构造的
# 1. 定义一个空字典
d0 = {}
print(type(d0))  # <class 'dict'>

d1 = {'语文': 77, '数学': 87, '英语': 85}
print(d1)  # {'语文': 77, '数学': 87, '英语': 85}

# 比列表的好处在于可以清晰的看出数据所表达的意义 [77, 87, 85]

# 2. dict构造
# 空字典
d2 = dict()
print(d2)  # {}

# 将其他序列转化成字典的时候 对这个序列有要求
'''
字典比较特殊 呈现一个数据的话需要两个值来配合 一个做键 一个做值
因此把其他序列转换成字典的话 这个序列得是二维的, 内层序列得有两个元素
[['语文', 77], ['数学', 78]]
'''
d3 = dict([('语文', 77), ('数学', 78), ('英语', 87)])
print(d3)  # {'语文': 77, '数学': 78}

d4 = dict(enumerate('abcdef'))  # enumerate('abcdef') 对序列重组  组合二维的  内层是二元组 (索引, 元素)
print(d4)  # {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

# 另外一种构造方式
# dict(变量名=数据值, 变量名1=数据值1)  # 把变量名转化为字符串类型  作为字典的键
d5 = dict(a=97, b=98, c=99, d=100)
print(d5)  # {'a': 97, 'b': 98, 'c': 99, 'd': 100}

5.7.2. 字典的运算符

scores = {'语文': 78, '数学': 97, '英语': 82, '政治': 77}

print('语文' in scores)  # True

print(77 in scores)  # False

print('历史' not in scores)  # True


scores1 = {'语文': 78, '数学': 97}
print(id(scores))
print(scores is scores1)
print(not scores is scores1)

# print(scores > scores1)
# TypeError: '>' not supported between instances of 'dict' and 'dict'

5.7.3. 字典的操作

scores = {'语文': 78, '数学': 97, '英语': 82, '政治': 77}

# 1. 添加数据
# 添加新的键值对
'''
字典数据[键] = 值
	键不存在  会将其作为新的键值对添加在字典中
	键若存在  将字典中该键对应的值进行修改
'''
scores['历史'] = 65
print(scores)  # {'语文': 78, '数学': 97, '英语': 82, '政治': 77, '历史': 65}

scores['英语'] = 28
print(scores)  # {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65}

'''
字典数据.setdefault(键, 值)
	键不存在  添加新的键值对
	键若存在  不做任何反应
'''
scores.setdefault('化学', 78)
print(scores)
# {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78}
scores.setdefault('数学', 79)
print(scores)  # {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78}

# 合并其他序列的元素
scores.update({'生物': 77, '地理': 56})
print(scores)
# {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56}

# 序列得是二维的
scores.update([('物理', 87), ('体育', 98)])
print(scores)
# {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56, '物理': 87, '体育': 98}


# 2. 删除数据
# 【根据键 把整个键值对就都删除】
'''
del 字典数据[键]
'''
del scores['历史']
print(scores)
# {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '化学': 78, '生物': 77, '地理': 56, '物理': 87, '体育': 98}

'''
字典数据.pop(键)
	和del的区别是  这个删完之后可以获取到键对应的值
'''
value = scores.pop('生物')
print(scores)  # {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '化学': 78, '地理': 56, '物理': 87, '体育': 98}
print(value)  # 77

'''
清空字典
'''
# scores.clear()
# print(scores)  # {}


# 3. 获取相关数据信息
# 根据键获取值
'''
变量名 = 字典数据[键]
	键若存在 获取键对应的数据值
	键若不存在 就报错
'''
value = scores['语文']
print(value)  # 78

# value = scores['生物']  # KeyError: '生物'

'''
变量名 = 字典数据.get(键)
	键若存在 获取键对应的数据值
	键若不存在 不会报错 返回的是None
'''
value = scores.get('语文')
print(value)  # 78

value = scores.get('生物')
print(value)  # None

# 当键不存在的时候 可以自定义相应的数据   键存在 还是把键对应的值返回
value = scores.get('语文', 0)
print(value)  # 78

value = scores.get('生物', 0)
print(value)  # 0

# 获取所有的键
all_keys = scores.keys()
print(all_keys)  # dict_keys(['语文', '数学', '英语', '政治', '化学', '地理', '物理', '体育'])  一维数据

# 获取所有的值
all_values = scores.values()
print(all_values)  # dict_values([78, 97, 28, 77, 78, 56, 87, 98])  一维数据

# 获取所有的键值组合
all_items = scores.items()
print(all_items)
# dict_items([('语文', 78), ('数学', 97), ('英语', 28), ('政治', 77), ('化学', 78), ('地理', 56), ('物理', 87), ('体育', 98)])
# 二维数据 内层是二元组 (键, 值)


# 4.其他的操作
# 拷贝字典
new_scores = scores.copy()
print(new_scores)

# 构造键序列构造字典[值默认为None]    dict.fromkeys(键)
d0 = dict.fromkeys('abcdefg')
print(d0)  # {'a': None, 'b': None, 'c': None, 'd': None, 'e': None, 'f': None, 'g': None}

# dict.fromkeys(键序列, 值)  # 给键设置值
d1 = dict.fromkeys('abcdefg', 0)
print(d1)
# {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0}


5.7.4. 字典的遍历

scores = {'语文': 78, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56}

# 直接遍历
for key in scores:
	print(key)
'''
语文
数学
英语
政治
历史
化学
生物
地理
'''

print('=' * 20)

# 等同于遍历  字典.keys()
for k in scores.keys():
	print(k, scores[k])
print('=' * 20)

# 直接遍历字典的所有的值
for v in scores.values():
	print(v)
'''
78
97
28
77
65
78
77
56
'''
print('=' * 20)

# *******  对字典进行操作 既要获取键 又要获取值  对字典的所有条目进行操作  字典.items()
for item in scores.items():
	print(item, item[0], item[1])  # 元组类型的数据
'''
('语文', 78)
('数学', 97)
('英语', 28)
('政治', 77)
('历史', 65)
('化学', 78)
('生物', 77)
('地理', 56)
'''
print('=' * 20)
# d0 = dict(scores.items())
# print(d0)

for k, v in scores.items():
	print(k, v)
# 语文 78
# 数学 97
# 英语 28
# 政治 77
# 历史 65
# 化学 78
# 生物 77
# 地理 56


5.7.5. 字典推导式

类似于列表推导式

格式 {键的变量: 值的变量 for 键的变量, 值的变量 in 字典.items() if 判断条件}

scores = {'语文': 88, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56}

# 获取成绩在80及其以上的 科目与成绩信息
'''
思路:
	1. 定以一个空字典 用来存储获取的信息
	2. 遍历获取所有的键值信息
	3. 判断操作 将符合要求的放在存储信息的字典中
'''
scores_80 = {}
# 遍历
for k, v in scores.items():
	if v >= 80:
		scores_80[k] = v
print(scores_80)  # {'语文': 88, '数学': 97}

print({k: v for k, v in scores.items() if v >= 80})

# 成绩在60到80之间的 科目及其成绩信息
scores_6080 = {}
print({k: v for k, v in scores.items() if 60 <= v <= 80})

总结:

字典:可以容纳多个数据、可以容纳不同类型的数据、每一份数据是KeyValue键值对、可以通过Key获取到Value,Key不可重复(重复会覆盖)、不支持下标索引、可以修改(增加或删除更新元素等)、支持for循环,不支持while循环

5.8. 容器类型总结

数据容器分类

数据容器可以从以下视角进行简单的分类:

  1. 是否支持下标索引:

    支持:列表、元组、字符串 - 序列类型

    不支持:集合、字典 - 非序列类型

  2. 是否支持重复元素:

    支持:列表、元组、字符串 - 序列类型

    不支持:集合、字典 - 非序列类型

  3. 是否可以修改:

    支持:列表、集合、字典

    不支持:元组、字符串

数据容器特点对比

列表元组字符串集合字典
元素数量支持多个支持多个支持多个支持多个支持多个
元素类型任意任意仅字符任意Key:Value Key:除字典外任意类型 Value:任意类型
下标索引支持支持支持不支持不支持
重复元素支持支持支持不支持不支持
可修改性支持不支持不支持支持支持
数据有序
使用场景可修改、可重复的一批数据记录场景不可修改、可重复的一批数据记录场景一串字符的记录场景不可重复的数据记录场景以Key检索Value的数据记录场景

基于各类数据容器的特点,它们的应用场景如下:

  • 列表:一批数据,可修改、可重复的存储场景
  • 元组:一批数据,不可修改、可重复的存储场景
  • 字符串:一串字符串的存储场景
  • 集合:一批数据,去重存储场景
  • 字典:一批数据,可用Key检索Value的存储场景

5.9. 容器综合案例

双色球

玩法规则:

“双色球”每注投注号码由 6 个红色球号码和 1 个蓝色球号码组成。红色球号码从 1—33 中选择,蓝色球号码从 1—16 中选择。 球的数字匹配数量和颜色决定了是否中奖。

具体中奖规则:

20200810164037883

需求:

1.生成本期双色球中奖号码。
(注意:1.生成的红球随机有序且不可重复、2.蓝球和红球的随机范围不同且篮球允许和红球重复)

2.两种产生数据方式

2.1通过控制台输入竞猜号码。

2.2自动生成

3.记录红球、蓝球竞猜正确球的数量,并根据获奖条件输出竞猜结果和本期双色球号码

运行效果图:

启动画面

iShot_2022-12-20_11.43.32

机选效果

iShot_2022-12-20_11.43.03

iShot_2022-12-20_11.47.56

自选效果

iShot_2022-12-20_11.42.42

iShot_2022-12-20_11.47.45

# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

import random


def get_custom_balls():
    # 准备一个彩票
    balls = []
    # 让用户输入选择
    while True:
        input_red = input("请输入6个红球(范围1-33): ")
        input_red = input_red.split()
        if len(input_red) != 6:
            print("红球数量错误,请重新输入")
            continue
        # 将6个红球转成整型
        input_red = [int(x) for x in input_red]
        # 对红球进行排序
        input_red.sort()
        # 判断红球是否越界
        if input_red[0] < 1 or input_red[5] > 33:
            print("红球越界了,请重新输入")
            continue
        # 判断红球是否重复
        if len(set(input_red)) < 6:
            print("红球重复了,请重新输入")
            continue

        balls += input_red
        break

    # 让用户输入蓝球
    while True:
        input_blue = int(input("请输入一个蓝球(范围1-16): "))
        if input_blue > 16 or input_blue < 0:
            print("蓝球越界,请重新输入")
            continue
        balls.append(input_blue)
        break

    return balls


def get_random_balls():
    # 准备一个红球池
    red_balls = list(range(1, 34))
    # 创建双色球
    balls = []
    # 循环6次,取6个红球
    for i in range(6):
        # 生成一个随机下标
        random_index = random.randint(0, len(red_balls) - 1)
        # 从红球池中获取一个随机的球,从中移除,并添加到双色球中
        balls.append(red_balls.pop(random_index))
    # 对红球排序
    balls.sort()
    # 随机篮球
    balls.append(random.randint(1, 16))

    return balls


def get_ball_desc(balls):
    red = map(lambda x: f"{x:02d}", balls[:6])
    blue = f"{balls[6]:02d}"
    return f"红球: {', '.join(red)}  蓝球: {blue}"


def get_ticket_money(level):
    mapping = {1: 5000000, 2: 500000, 3: 3000, 4: 200, 5: 10, 6: 5, 7: 0}
    return mapping.get(level, 0)


def check_balls(user_balls, ticket_balls):
    # 将用户选择的双色球、中奖号码双色球的红球部分提取到set中
    user_balls_set = set(user_balls[:6])
    ticket_balls_set = set(ticket_balls[:6])
    # 计算两个集合的交集,长度就是中奖号码的个数
    red_number = len(user_balls_set & ticket_balls_set)
    # 计算蓝球数量
    blue_number = 1 if user_balls[6] == ticket_balls[6] else 0

    # 记录中奖等级
    if red_number == 6 and blue_number == 1:
        ticket_level = 1
    elif red_number == 6 and blue_number == 0:
        ticket_level = 2
    elif red_number == 5 and blue_number == 1:
        ticket_level = 3
    elif red_number + blue_number == 5:
        ticket_level = 4
    elif red_number + blue_number == 4:
        ticket_level = 5
    elif blue_number == 1:
        ticket_level = 6
    else:
        ticket_level = 7

    return ticket_level, get_ticket_money(ticket_level)


def get_level_upper(ticket_level):
    mapping = {1: '一等奖', 2: '二等奖', 3: '三等奖', 4: '四等奖', 5: '五等奖', 6: '六等奖'}
    return mapping.get(ticket_level)


def user_operation():
    """
    用户的操作界面
    :return: None
    """
    print(f"{' 欢迎使用双色球系统 ':*^60}")
    while True:
        # 让用户输入自己的选择
        while True:
            user_choice = int(input("请输入您的选择: 1、自选号码  2、机选号码  0、退出系统  "))
            if user_choice in (0, 1, 2):
                break

        # 根据用户的选择,执行不同的操作,生成用户选择的双色球
        user_balls = []
        match user_choice:
            case 1:
                user_balls = get_custom_balls()
            case 2:
                user_balls = get_random_balls()
            case 0:
                break

        # 系统随机生成一注双色球,作为中奖号码
        ticket_balls = get_random_balls()

        # 匹配两注双色球,获取中奖等级以及奖金
        ticket_level, ticket_money = check_balls(user_balls, ticket_balls)

        # 打印最后的结果
        print(f"您的选择是: {get_ball_desc(user_balls)}")
        print(f"中奖号码是: {get_ball_desc(ticket_balls)}")
        if 1 <= ticket_level <= 6:
            print(f"🎉🎉🎉恭喜!!!您中了{get_level_upper(ticket_level)},奖金 {ticket_money:,}元!")
        else:
            print("很遗憾,您本次没有中奖,请再接再厉!")

    print("再见!欢迎下次再来使用!")


user_operation()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git安装以及git小乌龟使用

一、下载git 打开git官网地址&#xff1a;https://git-scm.com/进行下载 下载完安装&#xff0c;一直next就好&#xff0c;如果愿意就可以改下安装路径&#xff0c;改在d盘。 具体可以参考&#xff1a;git安装教程 二、安装完下载小乌龟以及语言包 下载地址&#xff1a;小乌龟…

【OpenMMLab AI实战营二期笔记】第六天 目标检测和MMDetection

1.什么是目标检测&#xff1f; 目标检测 vs 图像分类 目标检测的应用 &#xff08;1&#xff09;人脸识别 &#xff08;2&#xff09;智慧城市 &#xff08;3&#xff09;自动驾驶 &#xff08;4&#xff09;下游视觉任务&#xff1a;场景文字识别、人体姿态估计 目标检测技术…

微服务 springcloud 08.zuul框架,API网关,整合ribbon和hystrix框架

01.zuul是作为springcloud中的一个网关框架来使用的。 zuul API 网关&#xff0c;为微服务应用提供统一的对外访问接口。 zuul 还提供过滤器&#xff0c;对所有微服务提供统一的请求校验。 在项目中的位置&#xff1a; 02.新建 sp11-zuul 项目 03.pom.xml 需要添加 sp01-com…

【雕爷学编程】Arduino动手做(111)---震动提醒模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

纺织工厂运营神技,不会你就OUT了!

在纺织工业中&#xff0c;保持适宜的生产环境是至关重要的。温湿度、能耗、设备运行状态以及空气质量等因素对纺织品的质量和生产效率都有着重要影响。 为了实现对生产环境的全面监控和管理&#xff0c;纺织企业越来越多地采用动环监控系统。 客户案例 湖州市某纺织工厂监控项目…

USART2实现Motbus485通信

本文用的单片机是原子的战舰V4 1. 先来驱动一下usart2 USART驱动配置一般步骤: STEP1&#xff1a;使能相关时钟&#xff0c;这块板子usart2用到了A2、A3分别为TX脚、RX脚&#xff0c;D7的作用是发送接收模式控制。下面开启GPIO与USART2时钟&#xff1a; RCC_APB1PeriphClockCm…

SpringBoot中打印 sql 语句

系列文章目录 文章目录 系列文章目录前言一、在配置文件中 application.yml 配置即可二、#Log4g打印SqL语句三、配置Logback总结 前言 在SpringBoot中&#xff0c;我们可以使用日志框架来打印SQL语句&#xff0c;常用的日志框架有Logback和Log4j2。下面以Logback为例&#xff…

35:考虑virtual函数以外的其他选择

假设你正在写一个视频游戏软件&#xff0c;你打算为游戏内的人物设计一个继承体系&#xff0c;剧中人物被伤害或因其他因素而降低健康状态的情况并不罕见。你因此决定提供一个成员函数healthValue&#xff0c;它会返回一个整数&#xff0c;表示人物的健康程度。 由于不同的人物…

Linux x86_64平台同时编译x86_64和arm64两个架构的Qt应用程序出现XRes库无法找到

一 背景 在ubuntu x86_64平台上需要同时编译x86_64和arm64两个架构的Qt应用程序。在实践过程中&#xff0c;发现XRes库只能安装在其中一个平台。 二 根因 安装amd64版本的XRes库会删除arm64版本的库&#xff0c;反之亦然。 在安装amd64版本时&#xff0c;会删除arm64版本&a…

内部员工有没有在线帮助文档可以使用呢

当今企业中&#xff0c;内部员工的工作内容变得越来越复杂&#xff0c;需要不断学习新的知识和技能。在这种情况下&#xff0c;企业需要给员工提供一种便捷的在线帮助文档&#xff0c;使员工能够更加高效地完成工作任务。本文将介绍企业内部员工在线帮助文档的重要性以及如何建…

区块链如何助力价值互联网?这些专家有话说

6月13日&#xff0c;由开放原子开源基金会主办&#xff0c;XuperCore开源项目承办的2023开放原子全球开源峰会区块链分论坛在北京举办。来自区块链领域内的专家、行业代表汇聚一堂&#xff0c;分别以主题演讲、圆桌论坛等形式&#xff0c;阐述了全球区块链行业的新理念、新发展…

Opencv仿射函数getAffineTransform底层实现原理

推导 三角形ABC仿射成为三角形DEF的变换矩阵M 猜测矩阵M [ [a1,b1,c1], [a2,b2,c2] ] 仿射变换的数学联系 对于A点和D点 AX*a1AY*b1c1DX AX*a2AY*b2c1DY 对于B点和E点 BX*a1BY*b1c1EX BX*a2BY*b2c2EY 对于C点和F点 CX*a1CY*b1c1FX CX*a2CY*b2c2FY 求解 对以上数…

seqkit 两种拆分方法的比较

seqkit拆分fastq&#xff0c;fasta等文件有两种方式&#xff1a;split和split2&#xff0c; 二者的逻辑并不一样。 split 是将原文件拆分&#xff0c;写满第一个文件&#xff0c;再写第二个文件 split2是将原文件的内容&#xff0c;挨个写到各个拆分文件里面去&#xff1f; 比…

拓尔微技术干货 | get 5个知识点,了解细分驱动技术

本期我们对步进电机驱动原理、五线的步进电机和四线的步进电机、2-2相励磁和1-2相励磁、步进电机驱动的优化方案、拓尔微TMI8150B细分驱动技术的原理进行详细的介绍&#xff0c;共分为5个知识点&#xff0c;全是技术干货&#xff0c;赶紧get下来~ ✔get 1&#xff1a;步进电机…

datax安装部署使用 windows

Datax在win10中的安装_windows安装datax_JMzz的博客-CSDN博客 DataX/userGuid.md at master alibaba/DataX GitHub 环境准备&#xff1a; 1.JDK(1.8以上&#xff0c;推荐1.8) 2.①Python(推荐Python2.7.X) ②Python(Python3.X.X的可以下载下面的安装包替换) python3.0需…

Docker安装——CentOS7.6(详细版)

ps:docker官网 在 CentOS 上安装 Docker 引擎 |官方文档 &#xff08;&#xff09; 一、确定版本&#xff08;必须是7以上版本&#xff09; cat /etc/redhat-release 二、卸载旧版本&#xff08;或者之前装过&#xff0c;没有安装过就不用管了&#xff09; &#xff08;root用…

OpenCV 项目开发实战--实现填充图像中的孔( Python / C++ ) 代码实现

文末附分别基于C++和python实现的相关测试代码下载链接 图 1. 左:原始的图像。中心:阈值和倒置。右:孔被填充。 在本教程中,我们将学习如何填充二值图像中的孔洞。考虑图 1 中左侧的图像。假设我们想要找到一个将硬币与背景分开的二进制掩码,如右图所示。在本教程中,包含…

2.0C++继承

C继承概述 C 中的继承是指一个类可以从另一个类中继承属性和方法&#xff0c;这个被继承的类称为基类或父类&#xff0c;继承它的类称为派生类或子类。 C三种继承 1、公有继承 public 在公有继承中&#xff0c;基类的公有成员和保护成员都可以被派生类访问&#xff0c;而基…

【ROS】ROS2导航Nav2:简介、安装、测试效果、错误处理

1、简介 在ROS2中自动导航使用Nav2来实现。 Nav2 使用几个独立的模块化服务&#xff0c;通过 ROS 2接口&#xff08;例如动作服务器或服务&#xff09;与行为树 (BT) 通信。 Nav2 输入包括&#xff1a;TF转换、一个地图源、一个行为树 (BT) XML 文件和相关的传感器数据源; Nav…

【数字图像处理】2.几何变换

目录 2.1 仿射变换&#xff08;二维&#xff09; 2.2 投影变换&#xff08;三维&#xff09; 2.3 极坐标变换 2.3.1 将笛卡尔坐标转化为极坐标 2.3.2 将极坐标转换为笛卡尔坐标 2.3.3 利用极坐标变换对图像进行变换 几何变换&#xff1a;放大、缩小、旋转等&#xff0c;改…