零、索引 index&切片
索引操作的格式: seq[index]
切片:
seq[start: end: step]
- start: 起始索引,闭区间
步长为正数,start没有指定,默认为0/-len(seq)
步长为负数,start没有指定,默认为-1/len(seq) -1
- end: 结束索引,开区间
步长为正数,end没有指定,默认为len(seq)
步长为负数,end没有指定,默认为-len(seq)-1
- step: 步长,没有指定时,默认为1
步长为正数,表示从左往右取数据
步长为负数,表示从右往左取数据
注意:
1.如果start到end的方向和step的正负性不一致,则得到空序列
2.索引超出范围会报错,但切片不会
string = "Hello 1牛3 Python"
print(string[7:12:2])
print(string[5:-5:-2]) # 切片方向和step正负性不一致,得到空序列
print(string[1:160:2]) # 切片超出范围没有问题
print(sting[:])
print(string[::-1])
特点:
索引会降维,切片不会降维
一、格式化str
1.%格式化
符号 | 描述 |
---|---|
%s | 格式化为字符串 |
%d、%i | 格式化为十进制整数,仅适用于数字 |
%f、%F | 格式化为浮点数,默认精确到小数点后六位,仅适用于数字 |
%c | 格式化为字符,适用于整数(ASCII值)和字符(ASCII值对应的字符) |
%o | 格式化为八进制数,仅适用于整数 |
%x、%X | 格式化为十六进制数,仅适用于整数 |
print('🐲%c🐅' % 'A') # 🐲A🐅
# print('🐲%c🐅' % 'AA') # 报错 TypeError: %c requires int or char
print('🐲%c🐅' % 33) # 🐲!🐅
chr(i) / ord©
chr(i) 返回 Unicode 码位为指定整数的字符
ord© 返回指定字符对应的 Unicode 码位(整数)
print(chr(97))
print(ord('a'))
2.str的三种格式化
"""
编写一个程序, 帮助水果店实现计价功能:
请用户输入水果品种, 水果单价(元/kg)和重量(kg),
计算出需要花费的金额并做格式化输出
例:
用户输入水果品种为: 苹果
输入单价为: 3.98
输入重量为: 2.58
根据用户输入数据计算出总价为: 10.2684
请用三种字符串格式化方式输出如下结果:
您购买了2.58kg的苹果, 单价为3.98元/kg, 您需要支付10.27元!
"""
# %格式化
fruit_name = input("用户输入水果品种为:")
price = float(input("输入单价为:"))
weight = float(input("输入重量为:"))
total_amount = price * weight
print("您购买了%.2fkg的%s,单价为%.2f元/kg,您需要支付%.2f元!" % (weight, fruit_name, price, total_amount))
# format格式化
print("您购买了{:.2f}kg的{},单价为{:.2f}元/kg,您需要支付{:.2f}元!".format(weight, fruit_name, price, total_amount))
# f-string格式化
# {:.nf} 表示精确到小数点后n位
print(f'您购买了{weight:.2f}kg的{fruit_name},单价为{price:.2f}元/kg,您需要支付{total_amount:.2f}元!')
format 格式化传参比较灵活
name = '旺财'
age1 = 2
age2 = 3
# 传位置参数, 实参按照从左往右的顺序传入占位符{}
print('它说它叫{}, 它今年{}岁, 它宝宝{}个月了!'.format(name, age1, age2))
# 传关键字参数
print('它说它叫{n}, 它今年{a1}岁, 它宝宝{a2}个月了!'.format(n=name,a1=age1, a2=age2))
# 传实参的索引
print('它说它叫{1}, 它今年{0}岁, 它宝宝{2}个月了!'.format(age1, name, age2))
# 数据允许重复使用
print('它说它叫{n}, 它今年{a1}岁, 它宝宝{a1}个月了!'.format(n=name, a1=age1))
print('它说它叫{1}, 它今年{0}岁, 它宝宝{0}个月了!'.format(age1, name))
# {:.nf} 表示精确到小数点后n位
print('今天买了{}斤青菜, {}元/斤, 花了{:.2f}元!'.format(3.5, 2.59, 3.5*2.59))
二、字符串str的方法
方法的本质是函数(定义在类下的函数)
1.替换字符
str.replace(old, new[, count])
-
old:旧字符串
-
new:新字符串
-
count:要替换的最大次数,默认为-1,替换所有能替换的
用新字符串替换旧字符串并返回
string = "hello world"
string_new = string.replace('o', 'A')
print(string_new)
print(string)
print(string.replace('o', 'A', 1)) # 替换第一个o为A
print(string.replace('', '+')) # +h+e+l+l+o+ +w+o+r+l+d+
print(string.replace('ol', 'wb')) # 找不到就不替换,仍然返回原有的字符串"hello world"
print(string.replace('l','')) # heo word
2.移除左右字符
str.strip([chars])
-
chars:指定要移除的字符,如果没有指定,则默认移除空白符(空格、换行符、制表符)从字符串左右两边删除指定的字符
-
str.lstrip([chars]) 、str.rstrip([chars]) 也是同理,只不过一个是从左边删除,一个从右边删除而已
chars 与字符串不同,chars没有顺序,而字符串有顺序
string = "hello world"
print(string.strip('hds')) # ello worl
print(string.rstrip('hds')) # hello worl
print(string.strip('hds')) # ello world
3.居中填充
str.center(width[, fillchar])
-
width:指定字符串宽度
-
fillchar:指定填充的字符,默认为空格字符,只能是一个字符(char)
返回宽度为 width 的字符串,原字符串在其正中,使用指定的 fillchar 填充两边的空位;如果 width 小于等于 len(s) 则返回原字符串
string = "hello world"
# print(string.center(23, '==')) # 报错,TypeError: The fill character must be exactly one character long 填充字符只能为一个字符
print(string.center(15, '=')) # ==hello world==
print(string.center(14, '=')) # =hello world==
print('^'.center(9))
print('^^^'.center(9))
print('^^^^^'.center(9))
print('^^^^^^^'.center(9))
'''
^
^^^
^^^^^
^^^^^^^
'''
4.居左填充
str.ljust(width[, fillchar])
-
width:指定字符串宽度
-
fillchar:指定填充的字符,默认为空格字符
返回宽度为 width 的字符串,原字符串在其中靠左对齐,使用指定的 fillchar 填充空位;如果 width 小于等于 len(s) 则返回原字符串
str.rjust(width[, fillchar]) 也是同理,只不过原字符串在其中靠右对齐
5.判断前缀
str.startswith(prefix[, start[, end]])
- prefix:匹配的前缀,可以是字符串或者字符串组成的元组(元组中只要一个元素
满足即可)
-
start:开始索引(闭区间),不指定则默认为0
-
end:结束索引(开区间),不指定则默认为 len(s)
如果字符串以指定的 prefix 开始,返回 True,否则返回 False;start和end参数用
来控制判定的字符串区间。
string = "hello world"
print(string.startswith('he')) # True
print(string.startswith('')) # True
print(string.startswith(('lo', 'ld', 'he'))) # True
print(string.startswith('lo', 3, 8)) # True
print(string.startswith('lo', 4, 8)) # False
6.判断后缀
str.endswith(suffix[, start[, end]])
- suffix:匹配的后缀,可以是字符串或者字符串组成的元组(元组中只要一个元素
满足即可)
-
start:开始索引,不指定则默认为0
-
end:结束索引(不包括该索引),不指定则默认为 len(str)
如果字符串以指定的 suffix 结束,返回 True,否则返回 False;start和end参数用
来控制判定的字符串区间。
str1 = "hello world"
print(str1.endswith("d")) # True
print(str1.endswith("ld")) # True
print(str1.endswith("lo")) # False
print(str1.endswith("lo", 1, 5)) # True
print(str1.endswith(("d", "lo"))) # True
7.判断数字
str.isdigit()
判定字符串中的每个
字符是否都为数字,返回bool值
注意:负数和小数都判断为False
string = '1234'
print(string.isdigit()) # True
string = '-123'
print(string.isdigit()) # False
string = '1.23'
print(string.isdigit()) # False
8.字符串分割
str.split(sep=None, maxsplit=-1)
- sep:分隔符, 不指定时默认为所有的空白符(空格、换行、制表符), 并丢弃结果
中的空字符串
- maxsplit:最大分隔次数,默认为-1,即分隔所有
通过指定分隔符对字符串进行分割, 以字符串列表的形式返回(分割结果不包括分
隔符)
- str.rsplit(sep=None, maxsplit=-1) 也是同理,只不过是maxsplit从右边开始,但这并不意味着查找字符的顺序也是从右往左。比如从’hello world’ 中从后往前找’ol’,一样是找不到的。
注意:两个相同的分割字符分割后,中间有个空字符串""
string = "hello world"
print(string.split("l")) # ['he', '', 'o wor', 'd']
print(string.split('l', 2)) # ['he', '', 'o world'] 分割两次,分割为3份
print(string.split("ol")) # 没找到分隔字符,就返回原字符串列表 ['hello world']
print(string.rsplit("ol")) # 没找到分隔字符,就返回原字符串列表 ['hello world']
print(string.rsplit("lo")) # ['hel', ' world']
print(string.rsplit('l', 2)) # ['hel', 'o wor', 'd']
s = " Line1 \nLine2 \tLine3"
print(s.split(' ')) # ['', 'Line1', '\nLine2', '\tLine3']
print(s.split()) # ['Line1', 'Line2', 'Line3']
9.字符串拼接
str.join(iterable)
iterable:包括 string、list、tuple、dict、set等等
将可迭代对象中的元素(元素必须是字符串类型)以指定的字符串str连接,返回新的字符串
str1 = '123'
str2 = 'rtew'
print(str1.join(str2)) # r123t123e123w
# listprint(str1.join(list1))1 = ['1', 2, 'fd']
# print(str1.join(list1)) # 报错,因为list1中的所有元素必须为字符串,否则报错,因为一个数字是无法直接与字符串拼接的
list1 = ['1', '2', 'fd']
print(str1.join(list1)) # 11232123fd
10.字符出现次数
str.count(sub, [start[, end])
-
sub:需要查找的字符串
-
start:开始索引,默认为0
-
end:结束索引(开区间),默认为 len(str)
返回 sub 在字符串中出现的非重叠的次数
str1 = 'aaaaa'
print(str1.count('aaa')) # 1 记住非重叠
s = "hello world"
print(s.count('l'))
print(s.count('l', 3))
print(s.count('l', 3, 6))
print(s.count('l', 4, 6))
11.字符查找
str.find(sub[, start[, end]])
返回从左边开始第一次找到指定字符串时的正向索引,找不到就返回 -1
str.rfind(sub[, start[, end]])
返回从右边开始第一次找到指定字符串时的正向索引,找不到就返回 -1
str.index(sub[, start[, end]])
类似于find(),唯一不同在于,找不到就会报错
str.rindex(sub[, start[, end]])
类似于rfind(),唯一不同在于,找不到就会报错
-
sub:需要查找的字符串
-
start:开始索引,默认为0
-
end:结束索引(开区间),默认为 len(str)
s = 'hello world'
print(s.find('l'))
print(s.rfind('l'))
print(s.find('lo'))
print(s.rfind('lo'))
print(s.index('l'))
print(s.rindex('l'))
print(s.index('lo'))
print(s.rindex('lo'))
print(s.find('ol')) # -1
print(s.rfind('ol')) # -1
# print(s.index('ol')) # 报错ValueError: substring not found
# print(s.rindex('ol')) # 报错ValueError: substring not found
12.字符串首字母大写
str.capitalize()
将字符串的首字母变成大写,其他字母变小写,并返回。如果第一个元素不是字母,就直接把后面的字母变小写。
s = 'nihaoa'
print(s.capitalize()) # Nihaoa
s1 = '111nihaoA'
print(s1.capitalize()) # 111nihaoa
str.title()
将字符串中所有单词(python认为一到多个字母就是单词)的首字母变成大写,其他字母变小写,并返回。
s = '你好hELlo wo?rLD世界TuP'
print(s.title()) # 你好Hello Wo?Rld世界Tup
s = '你好hELlo wo?rLD世界u'
print(s.title()) # 你好Hello Wo?Rld世界U
str.upper()
将字符串中所有字符变成大写,并返回
str.lower()
将字符串中所有字符变成小写,并返回
str.swapcase()
将字符串中所有大写字符变成小写,小写变成大写,并返回
三、列表 list
1.对lst修改单个数据:
格式:lst[index] = object
lst = ['1', 2, True, [2, 2, 3], -1]
lst[1] = [1,1,4]
print(lst) # ['1', [1, 1, 4], True, [2, 2, 3], -1]
封包:当多个对象同时赋给一个变量时,此时会自动将这多个对象打包成一个元组。
a = 1, 'a', 9
print(a) # (1, 'a', 9)
a = 789, # 有逗号的话还是会生成一个元素的元组
print(a) (789,)
a = 789 # 这不是元组,是赋值
print(a) # 789
2.对lst修改多个数据:
1st[start:end:step]
= iterable —> 封包
lst = ['1', 2, True, [2, 2, 3], -1]
lst[:2] = 'ab'
print(lst) # ['a', 'b', True, [2, 2, 3], -1]
lst = ['1', 2, True, [2, 2, 3], -1]
lst[:2] = ['a','b']
print(lst) # ['a', 'b', True, [2, 2, 3], -1]
lst[:2] = 'dfaafd' # 列表内存自动管理。插入的数据长度过长或过短也是支持的,前提是步长为1(-1也会报错)。多了的话,后面的元素往后挪
print(lst) # ['d', 'f', 'a', 'a', 'f', 'd', True, [2, 2, 3], -1]
lst[:4] = '12'
print(lst) # ['1', '2', 'f', 'd', True, [2, 2, 3], -1] 少了的话,后面的元素往前靠
# 插入操作
lst = ['1', 2, True, [2, 2, 3], -1]
lst[0:1] = 'xyz'
print(lst) # ['x', 'y', 'z', 2, True, [2, 2, 3], -1]
lst = ['1', 2, True, [2, 2, 3], -1]
lst[:0] = 'xyz'
print(lst) # ['x', 'y', 'z', '1', 2, True, [2, 2, 3], -1]
lst = ['1', 2, True, [2, 2, 3], -1]
lst[:0] = ['xyz']
print(lst) # ['xyz', '1', 2, True, [2, 2, 3], -1]
lst = ['1', 2, True, [2, 2, 3], -1]
lst[-2:-2] = '🐶' # 步长为负要注意下,[-2:-2]等价于[3:3]
print(lst) # ['1', 2, True, '🐶', [2, 2, 3], -1]
3.list([iterable])
- 将一个iterable对象转化为列表并返回,如果没有实参,则返回空列表
string = 'abbd'
lst = list(string)
print(lst) # ['a', 'b', 'b', 'd']
print(list({1: 2, 3: 4})) # [1, 3] 字典只有键参与迭代
string = 'abcdef'
lst = list(string)
print(lst) # ['a', 'b', 'c', 'd', 'e', 'f']
print(len(lst)) # 6
new_str = str(lst)
print(new_str) # ['a', 'b', 'c', 'd', 'e', 'f']
print(len(new_str)) # 30
# lst -->str
print(''.join(lst)) # abcdef
4.list.append(x)
- 在列表的末尾追加一个元素,无返回值,相当于 a[len(a):] = [x]
lst = [1, 2, 3]
lst.append(9)
print(lst) # [1, 2, 3, 9] 直接修改lst,而没有创建新的列表
5.list.extend(iterable)
- 使用 iterable 中的所有元素来扩展列表,无返回值,相当于 a[len(a):] = iterab
- 注意与append方法区分,extend传的参数是一个可迭代对象,而append传参是一个元素
lst = [1, 2, 3]
lst.extend('abc')
print(lst) # [1, 2, 3, 'a', 'b', 'c']
6.list.insert(i, x)
-
i:要插入的元素的索引
-
x:要插入的元素
官方解释:
""" Insert object before index. """
在指定位置插入一个元素,无返回值,改变列表本身
注意:如果指定的索引超出了列表的当前长度,Python会将元素添加到列表的末尾,而不会抛出索引超出界限的错误。
lst = [1, 2, 3]
lst.insert(2,'fds') # [1, 2, 'fds', 3]
print(lst)
lst = [1, 2, 3]
lst.insert(6,'fds') # 这里的索引超出了列表长度
print(lst) # [1, 2, 3, 'fds']
7.list.sort( [key], reverse=False)
-
key:指定一个函数(可调用的对象), 在排序之前, 列表每个元素先应用这个函数,再根据返回值对原数据进行排序
-
reverse:默认为 False,代表升序,指定为 True 则为降序
对原列表进行排序,无返回值
如果比较的是字符,那会先取每个元素的第一位,去Unicode编码查找顺序的大小
print(ord('-')) # 45
print(ord(' ')) # 32
print(ord('0')) # 48
print(ord('1')) # 49
print(ord('2')) # 50
print(ord('9')) # 57
由上可知,负数会比正数小,空字符会比0小
lst = [1, 2, -5, -3]
# 升序排序
lst.sort()
print(lst)
# 降序排序
lst.sort(reverse=True)
print(lst)
lst = [1, 2, -5, '3']
lst.sort() # TypeError: '<' not supported between instances of 'str' and 'int'
lst = ['9', '-3', '100', '2', '10', '1']
lst.sort()
print(lst) # ['-3', '1', '10', '100', '2', '9']
# 元组的比较,先按照第一个元素比较,以此类推
lst = [(9, 1),(3, 6, 9, 1),(3, 6, 8, '9')]
lst.sort()
print(lst) # [(3, 6, 8, '9'), (3, 6, 9, 1), (9, 1)]
lst = [(9, 1),(3, 6, 9, 1),(3, 6, 9, '9')]
lst.sort()
print(lst) # TypeError: '<' not supported between instances of 'str' and 'int'
"""
对lst中的元素按照绝对值的大小降序排序
把lst中的每个元素依次作为实参传递给key所指定的函数去调用, 即:
abs(1), abs(2), abs(-5), abs(-3)
返回值分别为: 1, 2, 5, 3
根据返回值的大小对原数据进行排序
"""
lst.sort(key=abs, reverse=True)
print(lst)
sorted(iterable, [key], reverse=False)
-
iterable:可迭代对象(字符串,列表,元组,字典,集合等)
-
key:指定一个函数, 在排序之前, 每个元素都先应用这个函数之后再排序
-
reverse:默认为 False,代表升序,指定为 True 则为降序
对可迭代对象进行排序,以列表形式返回排序之后的结果
lst = [1, 2, -5, -3]
# 升序排序
print(sorted(lst))
# 降序排序
print(sorted(lst, reverse=True))
# 对lst中的元素按照绝对值的大小降序排序
print(sorted(lst, key=abs, reverse=True))
# 对字符串排序
print(sorted('hello world')) # [' ', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
8.list.reverse()
把列表中的元素倒过来,无返回值
注意:切片方式翻转列表的元素,会返回新的列表,有返回值
lst = [1, 3, 5, 2]
lst.reverse()
print(lst)
lst = [1, 3, 5, 2]
print(lst[::-1])
reversed(seq)
内置函数
- 返回给定序列的反向迭代器
lst = [1, 3, 5, 2]
obj = reversed(lst)
print(list(obj))
string = 'hello'
obj = reversed(string)
print(list(obj))
string = 'hello world'
r = reversed(string)
print(r) # <reversed object at 0x7fab88067490> 因为reversed返回的是一个迭代器对象
print(list(r)) # ['d', 'l', 'r', 'o', 'w', ' ', 'o', 'l', 'l', 'e', 'h']
print(list(r)) # []
1.迭代器一定是iterable
2.如果迭代器耗尽,则不能继续迭代
9. list.count(x)
- 返回元素 x 在列表中出现的次数
lst = [1, 2, 3, 2, '23', [2, 4]]
print(lst.count(2)) # 2
10.list.index(x[, start[, end]])
-
x:要找的值
-
start:起始索引,默认为 0
-
end:结束索引(闭区间),默认为 len(list)
返回从左边开始第一次找到指定值时的正向索引,找不到报错
lst = [1, 2, 3, 2, '23', [2, 4]]
print(lst.index(2))
print(lst.index(2, 4)) # ValueError
11.list.pop([i])
- i:要删除元素的索引
- 删除列表中指定索引的元素并返回该元素
- 如果没有指定索引,将会删除并返回列表中的最后一个元素
lst = [567, 'hello', True, False, 456]
print(lst.pop(1)) # 'hello'
print(lst) # [567, True, False, 456]
12.list.remove(x)
- 删除列表中从左往右遇到的第一个x元素,无返回值
- 如果没有这样的元素,则报错
lst = [1, 2, 4, 2, 3, 3]
lst.remove(2)
lst.remove(2)
print(lst)
13.list.copy()
- 返回列表的一个浅拷贝,等价于 a[:], a是列表名
lst = [567, 'hello', True, False, 456]
new_lst = lst.copy()
print(new_lst)
14.list.clear()
移除列表中的所有元素,无返回值,等价于 del a[:]
lst = [567, 'hello', True, False, 456]
lst.clear()
print(lst) # []
del : 可以移除变量
del 语句不是直接删除数据,而是解除对应的引用,当该数据的引用计数为0时,该数据就变为了一个可回收的对象,然后内存会被自动回收
lst = [567, 'hello', True, False, 456]
del lst
print(lst) # NameError: name 'lst' is not defined
lst = [567, 'hello', True, False, 456]
a = lst
del lst
print(a) # [567, 'hello', True, False, 456] del 语句不是直接删除数据,而是解除对应位置的引用
x = 1
lst = [567, x, 456]
del lst[1]
print(x) # 1 del 语句不是直接删除数据,而是解除对应位置的引用
remove()方法也是一样,删除的是引用
x = 1
lst = [567, x, 456]
lst.remove(x)
print(x) # 1
lst = ['abc', 3+4j, 789, [9.7, 'hello'], 345, 'xyz']
del lst[3][-1]
print(lst) # ['abc', (3+4j), 789, [9.7], 345, 'xyz']
lst = ['abc', 3+4j, 789, [9.7, 'hello'], 345, 'xyz']
del lst[1::2]
print(lst) # ['abc', 789, 345]
lst = ['abc', 3+4j, 789, [9.7, 'hello'], 345, 'xyz']
del lst[1], lst[2], lst[-2]
print(lst) # ['abc', 789, 'xyz'] 注意列表是动态的,删除之后索引会变化。 切片不一样,切片会同时操作
在Python中,函数参数可以以不同的方式传递,每种方式都有其特定的用途和语义。以下是Python中常见的参数分类:
-
位置参数(Positional Arguments):
这是最基本的参数类型,调用函数时按照函数定义中的顺序传入参数。def func(a, b, c): print(a, b, c) func(1, 2, 3) # 输出: 1 2 3
-
关键字参数(Keyword Arguments):
关键字参数允许你通过参数名来指定每个参数的值,这使得函数调用更加清晰,尤其是当函数有多个参数时。def func(a, b, c): print(a, b, c) func(a=1, b=2, c=3) # 输出: 1 2 3
-
默认参数(Default Arguments):
在函数定义时,可以为参数指定默认值。如果调用函数时没有提供该参数的值,则使用默认值。def func(a, b=5, c=10): print(a, b, c) func(1) # 输出: 1 5 10
-
可变位置参数(Arbitrary Positional Arguments):
使用星号(*)前缀来定义可变数量的位置参数。这些参数被存储在一个元组中。def func(*args): for arg in args: print(arg) func(1, 2, 3) # 输出: 1 2 3
-
可变关键字参数(Arbitrary Keyword Arguments):
使用两个星号(**)前缀来定义可变数量的关键字参数。这些参数被存储在一个字典中。def func(**kwargs): for key, value in kwargs.items(): print(key, value) func(a=1, b=2, c=3) # 输出: a 1 b 2 c 3
-
参数组合(Combining Arguments):
可以在函数定义中组合使用这些参数类型。def func(a, b, *args, c=0, **kwargs): print(a, b, args, c, kwargs) func(1, 2, 3, 4, c=5, d=6) # 输出: 1 2 (3, 4) 5 {'d': 6}
-
参数解包(Argument Unpacking):
可以在调用函数时使用星号(*)或双星号(**)来解包序列或映射,将其中的元素作为独立的参数传递。args = (1, 2, 3) kwargs = {'d': 4, 'e': 5} def func(a, b, c, d, e): print(a, b, c, d, e) func(*args, **kwargs) # 输出: 1 2 3 4 5
了解这些参数类型及其用法可以帮助你编写更灵活和强大的Python函数。
四、元组 tuple
-
不可变,是序列
-
元组用圆括号定义(圆括号可省略),没有元素类型限制
# 空元组
tup = ()
# 元组中只有一个元素时, 逗号不能省略
tup = (789,)
# 这不是元组,仍为数字789
tup = (789)
# 封包
tup = 'China', 1997, 2000
tup = ('China', 1997, 2000)
# 元组是不可变的, 但其中的可变成员仍然可以被改变
tup = (456, 'hello', ([789, 'world'],))
tup[0] = 987
print(tup) # TypeError: 'tuple' object does not support item assignment
tup = (456, 'hello', ([789, 'world'],))
tup[-1][0][0] = 987
print(tup)
tuple([iterable])
- 将一个iterable对象转化为元组并返回,如果没有实参,则返回空元组
print(tuple())
print(tuple("hello"))
print(tuple([1, 2, 3]))
# 字典作为一个iterable, 只有键参与迭代
print(tuple({1: 2, 3: 4})) # (1, 3)
print(tuple({'a', 'b', 'c', 789, 456}))
tuple.count(x)
- 返回元素 x 在元组中出现的次数
tup = (1, 2, 3, 2, '23', [2, 4])
print(tup.count(2))
tuple.index(x[, start[, end]])
- x:要找的值
- start:起始索引,默认为 0
- end:结束索引(闭区间),默认为 len(list)
- 返回从左边开始第一次找到指定值时的正向索引,找不到报错
tup = (1, 2, 3, 2, '23', [2, 4])
print(tup.index(2))
print(tup.index(2, 4)) # ValueError
元组为什么没有copy方法? 浅拷贝为什么对元组无效?
五、字典 dict
- 可变,不是序列,字典有顺序,没有下标,无法切片。但是可以索引,通过键去索引到值
- 字典用花括号定义,每个元素都是键值对的形式 key: value,是一种映射关系
- 字典的键不能存在可变的数据;值没有限制
- 字典的键如果重复,会自动去重,保留第一个重复键,并且其它重复的键对应的值
- 还会对第一个重复键对应的值进行修改;值可以重复。
- 当字典作为一个iterable对象参与操作时,只有键参与迭代。
d = {'name': 'Tony', 'age': 35, 'score': 98, [1,2]: 789}
print(d) # 报错TypeError: unhashable type: 'list' ,字典的键不能存在可变的数据
d = {'name': 'Tony', 'age': 35, 'score': 98, (1,2): 789}
print(d) # {'name': 'Tony', 'age': 35, 'score': 98, (1, 2): 789}
d = {'name': 'Tony', 'age': 35, 'score': 98, (1, 2, []): 789}
print(d) # 会报错,因为元组中存在可变数据:空列表
d = {'name': 'Tony', 'age': 35, 'score': 98, (1,2): 789, 'age': 40, 'age': 60}
print(d) # {'name': 'Tony', 'age': 60, 'score': 98, (1, 2): 789} 存在相同的键时,后面键的值会对第一个重复键对应的值进行修改
d = {'name': 'Tony', 'age': 35, 'score': 98, (1,2): 789}
print(list(d)) # ['name', 'age', 'score', (1, 2)] 当字典作为一个iterable对象参与操作时,只有键参与迭代
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
print(list(d)) # ['name', 'age', 'score', 'height']
print(tuple(d)) # ('name', 'age', 'score', 'height')
print(sorted(d)) # ['age', 'height', 'name', 'score'] 按字母大小排序的
print(''.join(d)) # nameagescoreheight
字典的增删改查
查:
注意:不存在的键,查找会报错
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
print(d['age']) # 35
print(d['name'])
print(d['age1']) # 不存在的键,查找会报错 KeyError: 'age1'
改、增:
注意:不存在的键,改会新增键值对
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
d['age'] = 42
print(d) # {'name': 'Tony', 'age': 42, 'score': 98, 'height': 789}
d['score'] = 100
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
d['gender'] = 'Male'
print(d) # {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789, 'gender': 'Male'}
删:
使用del 语句
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
del d['name']
print(d) # {'age': 35, 'score': 98, 'height': 789}
d = {'name': 'Tony', 'age': 35, 'score': 98, 'height': 789}
del d['name'],d['age']
print(d) # {'score': 98, 'height': 789}
创建字典六种方式
① 直接在空字典里面写键值对
d = {'name': 'Tom', 'age': 28}
print(d)
② 定义一个空字典,再往里面添加键值对
d = {} # d = dict()
d['name'] = 'Tom'
d['age'] = 28
print(d)
③ 使用dict内置函数
d = dict(name='Tom', age=28)
print(d) # {'name': 'Tom', 'age': 28}
④ 用可迭代对象来构建字典
d = dict([('name', 'Tom'), ('age', 28)])
print(d) # {'name': 'Tom', 'age': 28}
d = dict((('name', 'Tom'), ('age', 28)))
print(d) # {'name': 'Tom', 'age': 28}
⑤ 用**映射结构(mapping)**构建字典
d = dict(zip(['name', 'age'], ['Tom', 28]))
print(d)
d = dict({'name': 'Tony', 'age': 20}) # 虽然也可以传一个字典,但是因为本身就是字典,所以多此一举
print(d)
⑥ 利用类方法 fromkeys() 创建
d1 = dict.fromkeys(('name', 'age', 'height'))
print(d1)
d2 = dict.fromkeys(('name', 'age', 'height'), 'abc')
print(d2)
dict(**kwargs) / dict(mapping) / dict(iterable)
- 用于创建一个字典并返回
print(dict())
print(dict(one=1, two=2, three=3))
print(dict(zip(['one', 'two', 'three'], [1, 2, 3])))
print(dict([('one', 1), ('two', 2), ('three', 3)]))
zip(*iterables) 不定长参数(可传0-无穷个位置参数)
- 返回一个迭代器,在进行迭代操作时,其中的第 i 个元组包含来自每个可迭代对象的第 i 个元素
- 当所输入可迭代对象中最短的一个被耗尽时,迭代器将停止迭代
- 不带参数时,它将返回一个空迭代器
obj = zip('abcd', [4, 5, 7, 1])
print(obj) # <zip object at 0x7fc070221b40>
print(list(obj)) # [('a', 4), ('b', 5), ('c', 7), ('d', 1)]
iter1 = 'ghwk'
iter2 = (9, 3, 'xyz', 6)
iter3 = {1: 2, 3: 4}
var = zip(iter1, iter2, iter3)
print(list(var)) # [('g', 9, 1), ('h', 3, 3)]
不定长参数:
*args:可以接收[0, +∞)个位置参数, 贪婪的,将它们打包成一个元组,如果没有接收到任何实参,就是空元组。
**kwargs:可以接收[0, +∞)个关键字参数, 贪婪的,将它们打包成一个字典,如果没有接收到任何实参,就是空字典
要求:**kwargs必须放在所有形参的最后,否则报错
def func(*x):
return x
print(func()) # ()
print(func(1, "2", [2, 3, 4])) # (1, '2', [2, 3, 4])
def func(**x):
return x
print(func()) # {}
print(func(a='xxx', b=[1,'d',('fd', '3')],c=2)) # {'a': 'xxx', 'b': [1, 'd', ('fd', '3')], 'c': 2}
def func(*x, **y):
print(x)
print(y)
func(1,23,6, k='33', g=4)
'''
(1, 23, 6)
{'k': '33', 'g': 4}
'''
#def func(**x, *y): # 报错
# print(x)
# print(y)
#
#
# func(k='33', g=4, 1, 23, 6)
classmethod fromkeys(iterable[, value])
- 以 iterable 的每个元素作为键,value 作为每个键的所有值,创建一个字典,value 不指定时,默认为 None
- 键不同,值相同
dic1 = dict.fromkeys(("name", "age", "gender"))
print(dic1) # {'name': None, 'age': None, 'height': None}
dic2 = dict.fromkeys(("name", "age", "gender"), "I don't know!")
print(dic2) # {'name': 'abc', 'age': 'abc', 'height': 'abc'}
dict.keys()
- 返回由字典键组成的一个新视图
- 返回的对象是视图对象,这意味着当字典改变时,视图也会相应改变
d = {'name': 'Tom', 'age': 15, 'height': 162}
view_keys = d.keys()
print(view_keys) # dict_keys(['name', 'age', 'height'])
# 修改字典
d['weight'] = 59
print(view_keys) # dict_keys(['name', 'age', 'height', 'weight'])
视图对象的特点:
1.可迭代性 2.动态性
可迭代性: 可以转换为字符串、列表或者元组
dict.values()
- 返回由字典值组成的一个新视图
- 返回的对象是视图对象,这意味着当字典改变时,视图也会相应改变
d = {'name': 'Tom', 'age': 15, 'height': 162}
view_values = d.values()
print(view_values) # dict_values(['Tom', 15, 162])
# 修改字典
d['weight'] = 59
print(view_values) # dict_values(['Tom', 15, 162, 59])
dict.items()
- 返回由字典键值对组成的一个新视图
- 返回的对象是视图对象,这意味着当字典改变时,视图也会相应改变
d = {'name': 'Tom', 'age': 15, 'height': 162}
view_items = d.items()
print(view_items) # dict_items([('name', 'Tom'), ('age', 15), ('height', 162)])
# 修改字典
d['weight'] = 59
print(view_items)
dict.get(key, default=None)
- key:键
- default:如果指定的键不存在时,返回该值,默认为 None
- 返回指定的键 key 对应的值, 如果 key 不在字典中,则返回 default
d = {'name': 'Tom', 'age': 15, 'height': 162}
print(d.get('age')) # 15
print(d.get('weight')) # None
print(d.get('weight', '该键不存在')) # 该键不存在
字典是可变的
dict.update([other])
- 使用来自 other 更新字典,没有返回值,如果键已经存在,就更新值,如果键不存在就新增键值对
- 可以像 dict() 那样传参,dict(**kwargs) / dict(mapping) / dict(iterable)
d = {'name': 'Tom', 'age': 15, 'height': 162}
d.update(age=18, weight=59)
d.update({'age': 18, 'weight': 59})
d.update(zip(['age', 'weight'], [18, 59]))
d.update([('age', 18), ('weight', 59)])
print(d)
d = {'name': 'Tom', 'age': 15, 'height': 162}
d.update(age=18, weight=59)
print(d) # {'name': 'Tom', 'age': 18, 'height': 162, 'weight': 59}
dict.pop(key[, default])
- key:键
- default:指定当键不存在时应该返回的值
- 移除指定的键所对应的键值对 , 并返回该键对应的值, 如果该键不在字典中,则返回 default 指定的值
- 如果 default 未指定值且指定的键不存在于字典中,则报错
d = {'name': 'Tom', 'age': 15, 'height': 162}
print(d.pop('height')) # 162
print(d) # {'name': 'Tom', 'age': 15}
print(d.pop('weight', None)) # None
print(d.pop('weight')) # KeyError: 'weight'
dict.popitem()
- 从字典中移除最后一个键值对, 并返回它们构成的元组 (键, 值)
d = {'name': 'Tom', 'age': 15, 'height': 162}
print(d.popitem()) # ('height', 162)
print(d) #{'name': 'Tom', 'age': 15}
d = {}
print(d.popitem()) # KeyError: 'popitem(): dictionary is empty'
dict.setdefault(key, default=None)
- 如果字典存在指定的键,则返回它的值
- 如果不存在,返回 default 指定的值,并且新增该键值对
d = {'name': 'Tom', 'age': 15, 'height': 162}
print(d.setdefault('age')) # 15
print(d.setdefault('age',20)) # 15
print(d) # {'name': 'Tom', 'age': 15, 'height': 162}
print(d.setdefault('weight')) # None
print(d) #{'name': 'Tom', 'age': 15, 'height': 162, 'weight': None}
print(d.setdefault('gender', 'male')) # male
print(d) # {'name': 'Tom', 'age': 15, 'height': 162, 'weight': None, 'gender': 'male'}
dict.copy()
- 返回原字典的浅拷贝
d = {'name': 'Tom', 'age': 15, 'height': 162}
new_d = d.copy()
print(new_d) # {'name': 'Tom', 'age': 15, 'height': 162}
dict.clear()
移除字典中的所有元素,无返回值
d = {'name': 'Tom', 'age': 15, 'height': 162}
d.clear()
print(d) # {}
六、集合(Set)
- 可变,不是序列
- 集合也用花括号定义,但其中的元素不是键值对
- 集合中不能存在可变的数据(列表,字典,集合,字节数组)
- 集合是无序的
- 集合的元素如果重复,会自动去重
- 创建空集合必须用 set(),因为 { } 是用来创建空字典的
s = {{1},{1}} # TypeError: unhashable type: 'set'
s = {[1, 2]} # TypeError: unhashable type: 'list'
s = {(1, 2, 4)} # ok
s = {{'name': 'fsa'},{'age': 20}} # TypeError: unhashable type: 'dict'
s = set()
print(s) # set()
问题:python的集合是无序的,但是为啥每次打印顺序相同,底层的原理是啥?
Python中的集合(set)确实是无序的,这意味着集合中元素的存储顺序并不是按照你添加它们的顺序来维护的。然而,在Python 3.7+中,字典(dict)和集合(set)都使用了一种叫做“哈希表”(hash table)的数据结构,这种数据结构保证了元素的插入顺序。因此,当你对集合进行迭代或者打印时,元素出现的顺序可能看起来是“有序”的,这实际上是因为元素被添加到集合中的顺序。
在Python 3.6中,引入了一个叫做“有序字典”(OrderedDict)的类,它记住了元素添加的顺序。在Python 3.7中,普通的字典和集合都被修改为记住元素的插入顺序。这是语言层面的一个变化,旨在让这些数据结构的行为更加可预测。
尽管如此,集合的无序性意味着它不保证在所有的操作中都保持元素的顺序。例如,当你对集合进行某些操作,如合并(union)或交集(intersection)时,结果集合中元素的顺序可能会与原始集合中元素的顺序不同。
此外,集合的无序性还意味着它不提供支持索引或排序的功能。如果你需要有序的集合,你可能需要使用列表(list)或其他数据结构,如有序字典(OrderedDict),它提供了记住元素插入顺序的字典实现。
总结一下,尽管Python的集合在打印时可能显示出元素的顺序,但这并不意味着集合是有序的。这种顺序性是由于哈希表的实现细节,而不是集合本身的属性。集合的主要特点是它是一个无序的、不包含重复元素的集合。
set([iterable])
-
将一个iterable对象转化为集合并返回,如果没有实参,则返回空集合
print(set()) print(set("hello")) print(set([1, 2, 3])) print(set((1, 2, 3))) # 字典作为一个iterable, 只有键参与迭代 print(set({1: 2, 3: 4})) ''' set() {'e', 'h', 'l', 'o'} {1, 2, 3} {1, 2, 3} {1, 3} '''
利用集合特性,可以用来 去重 和 关系测试
# 把iterable变成集合,就会自动去掉重复的元素
lst = [1, 2, 4, 5, 7, 7, 4, 5]
s = set(lst)
print(list(s)) # [1, 2, 4, 5, 7]
# 集合可以利用操作符做关系测试
a = set('abdefga')
b = set('abc')
c = set('aef')
print(a >= b) # 判断a是否为b的父集
print(c <= a) # 判断c是否是a的子集
print(c < a) # 判断c是否是a的真子集
print(a - b) # 返回a和b的差集
print(b - a) # 返回b和a的差集
print(a | b) # 返回a和b的并集
print(a & b) # 返回a和b的交集
print(a ^ b) # 返回a和b的对称差集
# 优先级: - & ^ |
print(a - b | c ^ b & a)
'''
False
True
True
{'g', 'f', 'd', 'e'}
{'c'}
{'g', 'c', 'e', 'a', 'f', 'b', 'd'}
{'a', 'b'}
{'g', 'c', 'e', 'f', 'd'}
{'g', 'b', 'd', 'e', 'f'}
'''
问题:什么是对称差集
对称差集(Symmetric Difference)是集合论中的一个概念,它表示两个集合中不重叠的部分。换句话说,它由那些在两个集合中唯一存在的元素组成,不包括那些同时在两个集合中都存在的元素。
给定两个集合 A 和 B,它们的对称差集 AΔB可以定义为:
AΔB=(A−B)∪(B−A)
这里的 A−B* 表示集合 A 中有而集合 B 中没有的元素,B−A 表示集合 B 中有而集合 A 中没有的元素。对称差集也可以通过异或(XOR)操作来计算,即:
AΔB=(A∪B)−(A∩B)
这意味着对称差集包含了在 A 或 B 中的元素,但不包括同时在两者中的元素。
例如,如果有两个集合 A={1,2,3} 和 B={2,3,4},它们的对称差集是:
AΔB={1,4}
因为 1 在 A 中但不在 B中,而 4 在 B 中但不在 A中。元素 2 和 3 不包括在内,因为它们同时出现在两个集合中。
set.update(*others)
- others:Iterables,上一个可以传*iterables参数的是zip()
- 更新集合,添加来自 others 中的所有元素
s = '15'
lst = [1, '2']
d = {1: '1', 2: '2'}
set1 = {'1', '2', 1, 3}
set1.update(s, lst, d)
print(set1) # {1, 2, 3, '5', '2', '1'}
set.add(elem)
- 将元素 elem 添加到集合中。如果元素已经存在,则没有影响
s = {1, 2, 3}
s.add("hello world")
print(s) # {1, 2, 3, 'hello world'}
set.remove(elem)
- 从集合中移除元素 elem。 如果 elem 不存在,则报错
s = {1, 2, 3, 4}
s.remove(3)
print(s)
s.remove(3) # 报错
set.discard(elem)
- 从集合中移除元素 elem。 如果 elem 不存在,则不做任何操作
s = {1, 2, 3, 4}
s.discard(3)
s.discard(3)
s.discard(3)
print(s)
set.pop()
- 从集合中移除并返回 任意一个元素。如果集合为空,则报错
s = {'1', '2', 'hello', 789}
print(s.pop())
print(s)
set.copy()
返回原集合的浅拷贝
set1 = {'1', '2', 1, 3}
set2 = set1.copy()
print(set2)
set.clear()
从集合中移除所有元素
s = {'1', '2', 'hello', 789}
s.clear()
print(s)
总结:
数字,字符串,列表,元组,集合,字典
序列:字符串、列表、元组
可变数据类型:列表、集合、字典
可以求长度的数据类型:字符串,列表,元组,集合,字典
可迭代对象:字符串,列表,元组,集合,字典