python-字符编码、字符串格式化、字符串方法、列表、元组、字典、集合等基础知识总结
目录:
计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号
ascii用1个字节代表一个字符;
unicode常用2个字节代表一个字符,生僻字需要用4个字节;
UTF-8英文字母被编码成1个字节,汉字通常是3个字节有很生僻的字符才会被编码成4-6个字节。
字母x,用ascii表示是十进制的120,二进制0111 1000
汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。
字母x,用unicode表示二进制0000 0000 0111 1000,所以unicode兼容ascii,也兼容万国,是世界的标准
这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:
字符 |
Ascll |
Unicode |
Utf-8 |
x |
01000001 |
00000000 01000001 |
01000001 |
中 |
不能表示 |
01001110 00101101 |
11100100 10111000 10101101 |
从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
ASCII:只能存英文和拉丁字符,一个字符占一个字节,8位
gb2312:只能存6700多个中文,1980年
gbk1.0:存2万多字符,1995年
gb18030:存27000中文,2000年
万国码:Unicode:utf-32 一个字符占4个字节
Utf-16 一个字符占2个字节,或两个以上。
Utf-8 一个英文用ASCII码来存,一个中文占3个字节
声明编码 -*- coding:utf-8 -*-
gbk默认不认识utf-8,utf-8是Unicode的一个子集
Unicode 默认向下兼容gbk等
python3内部默认是 unicode,文件默认编码是utf-8
阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符
ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符),后来为了将拉丁文也编码进了ASCII表,将最高位也占用了
阶段二:为了满足中文和英文,中国人定制了GBK
GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符
为了满足其他国家,各个国家纷纷定制了自己的编码
日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里
阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。如何解决这个问题呢???
说白了乱码问题的本质就是不统一,如果我们能统一全世界,规定全世界只能使用一种文字符号,然后统一使用一种编码,那么乱码问题将不复存在,
很多地方或老的系统、应用软件仍会采用各种各样的编码,这是历史遗留问题。于是我们必须找出一种解决方案或者说编码方案,需要同时满足:
1、能够兼容万国字符
2、与全世界所有的字符编码都有映射关系,这样就可以转换成任意国家的字符编码
这就是unicode(定长), 统一用2Bytes代表一个字符, 虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符编码表
很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)
阶段四:于是产生了UTF-8(可变长,全称Unicode Transformation Format),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存。
Python 支持格式化字符串的输出 。尽管这样可能会用到非常复杂的表达式,但最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。
格式输出汇总:
1 #第一种
2 val = "我叫%s,今年%d岁,身高%d"%('zrh',20,175)
3 print(val) #运行结果:我叫zrh,今年20岁,身高175
4 #第二种
5 val = "我叫{0},今年{1}岁,身高{2},我弟弟身高也是{2}"
6 val1 = val.format("zrh",20,175)
7 print(val1) #运行结果:我叫zrh,今年20岁,身高175,我弟弟身高也是175
8 #第三种
9 v = input("your name:") #用户输入姓名
10 val = "我叫{name},今年{age}岁,身高{height}"
11 val1 = val.format(name=v,age="20",height="175") #name = v是用户输入的那个姓名
12 print(val1)
13 #第四种
14 val = "我叫{name},今年{age}岁"
15 dic1 = {"name":"zrh","age":20}
16 val1 = val.format(**dic1)
17 print(val1)
18 #第五种
19 name = "我叫{name},年龄{age}"
20 val = name.format_map({'name':'海角','age':18}) #只有一种写法,里面必须是字典
21 print(val)
如果在格式化输出中想要输出%号,就要用到%%格式
print("我是%s,我的进度已经完成80%%" %('zrh'))
输出结果:
我是zrh,我的进度已经完成80%
%06d表示数字用6位表示,数字不足6位的话用0代替
from math import *
a = log(e**2)
print('%.2f'%(a)) #输出结果:2.00
百分号的输出:
num = 0.1
print("数据比例为 %.2f%%"%(num*100))
#输出结果:数据比例为 10.00%
变量名关键字:
python在定义变量名时区分大小写
import keyword as kw
print(kw.kwlist)
#['False', 'None', 'True', 'and', 'as', 'assert', 'async',
# 'await', 'break', 'class', 'continue', 'def', 'del', 'elif',
# 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import',
# 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return',
# 'try', 'while', 'with', 'yield']
转移符号相关问题:
\t 表空格
\n表换行
如果字符串中需要输出\n、\t等,需要加两个\\
print("\\n") #输出结果 \n
如果字符串中需要输出的“\”非常多的话,可以使用原始字符串模式打印,即在字符串前输入r
如果字符串超过一行,再给变量赋值时需要使用三引号
case = '''
超过一行的字符串
'''
运算问题:
% 取余
\\ 整除
取余的原理
print(10 % 3) #输出结果 1
print(10 % -3) # 输出结果 -2
整除的原理:结果向下取整
进制也就是进制位,我们常用的进制包括:二进制、八进制、十进制与十六进制,它们之间区别在于数运算时是逢几进一位。比如二进制是逢2进一位,十进制也就是我们常用的0-9是逢10进一位,16进制的10-15用A、B、C、D、E、F来表示。
1. 十进制转二进制
方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。
2. 二进制转十进制
方法为:把二进制数按权展开、相加即得十进制数。
第一个的1*2的7次方,是因为数位就是8位,8-1=7,依此类推。
#十进制转二进制
print(bin(175)) #0b10101111
#十进制转八进制
print(oct(175)) #0o257
#十进制转16进制
print(hex(175)) #0xaf
Python有五个标准的数据类型:
Numbers(数字) V = 1 int类
Boolean value(布尔值) V = True (bool类)
String(字符串) V = “Good” (str类)
List(列表) V = [“good”,”best”] (list类)
Tuple(元组) V = (“good”,”best”) (tuple类)
Dictionary(字典) V = {“name”:”zrh”,”age”:20} (dict类)
字符类型的相互转换
1.int类(记住一个)
bit_length()表示当前十进制数用二进制数表示时,最少使用的位数。
代码示例:
count = 16
v = count.bit_length()
print(v,"---",count)
输出结果:
5 --- 16
注意:
count = "1"
count1 = "2"
print(count+count1) #输出结果:12 字符串的加法是拼接的作用
count2 = 1
count3 = 2
print(count2+count3) #输出结果:3 数字的加法是加法作用
#需求,输入一个数字,然后每个数字相加,列入输入152,结果就是1+5+2
count4 = "152" #在数字和字符串中只有字符串才可以遍历,所以要把count4转为str类型
val = 0
for i in range(len(count4)):
val += int(count4[i]) #count4[i]是字符串,所以要转为数字才能相加
print(val)
浮点数:
对于字符串,执行内置命令后,原来的值不变。
2.1:upper()转换字符串中的小写字母为大写
代码示例:
name = "zrh"
v = name.upper()
print(v,"---",name)
输出结果:
ZRH --- zrh
2.2:lower()转换字符串中所有大写字符为小写
代码示例:
name = "ZrH"
v = name.lower()
print(v,"---",name)
输出结果:
zrh --- ZrH
2.3:capitalize()将字符串的第一个字符转换为大写
代码示例:
name = "zrh"
v = name.capitalize()
print(v,"---",name)
输出结果:
Zrh --- zrh
2.4:strip()去除首尾的内容 空格、换行符、制表符、指定内容
代码示例:
name = " zrh "
v = name.strip()
print(v+"---",name)
输出结果:
zrh--- zrh
name_1 = "\tzrh\t"
print(name_1)
print(name_1.strip())
输出结果:
( zrh )空格是\t的结果
(zrh)
name_1 = "zrh"
print(name_1)
print(name_1.strip("h"))
输出结果:
zrh
zr
2.5:lstrip()截掉字符串左边的空格或指定字符
2.6:rstrip()删除字符串字符串末尾的空格
2.7:replace(str1, str2 , max)将字符串中的 str1 替换成 str2,如果max指定,则替换不超过max次
代码示例:
content = "人生自古谁无死,早死晚死都得死"
v = content.replace("死","*",2)
print(v,"---",content)
输出结果:
人生自古谁无*,早*晚死都得死 --- 人生自古谁无死,早死晚死都得死
2.8: len(string)返回字符串长度
代码示例:
content = "人生自古谁无死,早死晚死都得死"
v = len(content)
print(v)
输出结果:
15
2.9:[]根据索引取值
代码示例:
#索引值从0开始计算不是从1
content = "人生自古谁无死,早死晚死都得死"
v = content[0] #取字符串的第一个字符
v1 = content[-1] #-代表从后往前找,1代表第一个,所以-1代表正向的最后一个
v2 = content[0:5] #从0开始取到索引值为4的对象,不包括索引值为5的对象,相当于数学中的左闭右开区间
v3 = content[8:] #从索引值为8的对象开始取到最后一个
v4 = content[0:15:2] #从0开始隔一个取一个,一直取到14,2表步长表示隔一个取一个,3就表示隔2个
print(v,v1,v2,v3,v4)
输出结果:
人 死 人生自古谁 早死晚死都得死 人自谁死早晚都死
2.10 :split(“str”,num) ()里没有参数的话,默认是空格
以 str 为分隔符截取字符串,如果 num 有指定值,则仅截取 num+1 个子字符串
代码示例:
content = "人生自古谁无死,早死晚死都得死"
v = content.split("死",2)
print(v)
输出结果:
['人生自古谁无', ',早', '晚死都得死']
2.11 :.isdecimal()判断当前字符串中是否全部都是数字
代码示例:
v = "a123"
c = v.isdecimal()
print(c)
输出结果:
False
补充:
python中isdigit()、isdecimal()和isnumeric的区别
a = "good 1 night 2"
a.isdecimal() #如果a中只有十进制字符,则返回True,否则为False
a.isdigit() #如果a中的所有字符都是数字,并且在S中至少有一个字符,则返回True
a.isnumeric() #如果a中只有数字字符,则返回True,否则为False
2.12 :join(seq) 以指定字符串作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
seq里的元素必须是字符串,不能是数字,数字和字符串(前面的“_”)不能相加,
代码示例:
list1 = ['alex','zrh','sdv']
a = '_'.join(list1) #这里的_就表示用_连接
b = "".join(list1) #""里什么都没有表示直接连接
print(a)
print(b)
输出结果:
alex_zrh_sdv
alexzrhsdv
2.13:把字符串转换成字节encode()
name = "天下"
name.encode("utf-8") #把字符串(Unicode)转换成字节(utf-8格式)
name.encode("gbk") #把字符串(Unicode)转换成字节(gbk格式)
2.14:count()
count() 方法用于统计字符串里某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。
name = "ooxxooxxooxx"
print(name.count("o"))
#有两个参数,不写默认为print(name.count("o",0,len(name)))
#0表示条件统计起始索引值,len(name)表示终止索引值
2.15:expandtabs() 方法把字符串中的 ('\t')转为空格,('\t')默认的空格数是 8,\t 表示横向制表符 \n表示换行符
name = "ID\tname\tpasswd\n1\tzrh1\t123\n2\tzrh2\t123"
val = name.expandtabs(20) #20表示连同\t前面的内容一共占20个字符的位置
print(val)
输出结果:
2.16其他不常用的方法汇总:
1.数字转字符串 str(对象)
2.字符串转数字 int(对象)
对象必须是形为数字,才能转换
Int(string)就会报错
3.数字转布尔值 bool(对象)
bool(0)是False
其他不是0的数都是True
但是在其他方面true = 1 flase = 0
4.字符串转布尔值 bool(对象)
bool(“”)是False
其他任何字符串都是True
代码示例:
a = 9 or 2>3
print(a)
输出结果:9
代码示例:
a = 0 or 2>3
print(a)
输出结果:False
代码示例:
a = 0 or 6
print(a)
输出结果:6
代码示例:
a = 0 or 2<3
print(a)
输出结果:True
5.元组转列表
v = (1,2,3)
val = list(v)
6.列表转元组
v = [1,2,3]
val = tuple(v)
7.列表转字符串
v = ["1","2","3"]
result = "".join(v)
print(result)
Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串。
for循环的一般格式如下:
for 变量接收名 in 对象 :
代码示例:
list1 = ["one","two","three",4]
for i in list1:
print(i)
输出结果:
one
two
three
4
For循环时加上序号enumerate:
list1 = ["手机","电脑","ipad"]
for i,v in enumerate(list1,1): #表示遍历list1这个列表,序号从1开始。
print(i,v)
输出结果:
1 手机
2 电脑
3 ipad
循环语句可以有 else 子句,它在穷尽列表(以for循环)或条件变为 false (以while循环)导致循环终止时被执行,但循环被break终止时不执行,简而言之就是break后不会执行下级的else(注意break的级别)
range()函数
如果你需要遍历数字序列,可以使用内置range()函数,它会生成数列
range(起始值,终止值,步长)这里是左闭右开区间,可以取到起始值,但是取不到终止值,只能取到终止值的前一个,步长就是遍历时的距离,默认是1
代码示例:
for i in range(5,1,-1):
print(i)
输出结果:
5
4
3
2
range的组和用法:
可以结合range()和len()函数以遍历一个序列的索引:
list1 = ["手机","电脑","ipad"]
for i in range(len(list1)): #len是从1开始,range没写参数是从0开始
print(i,list1[i])
输出结果:
0 手机
1 电脑
2 ipad
print中的自动换行
print 会自动在行末加上回车, 如果不需回车,只需在 print 语句的结尾添加一个逗号 , 并设置分隔符参数 end,就可以改变它的行为。
a = 1
b = 2
if a < b :
c = b
else:
c = a
这样写代码非常繁琐,所以在遇到if else非常简单的时候,可以用到三元运算
a = 1
b = 2
c = b if a < b else a
①---⑥表示写三元运算时候的流程
列表是Python中最基本的数据结构。列表中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。
如下所示:
list = ["one","two",3,4,"five"]
列表可以进行 增、删、改、查。如果列表只有一个对象,在后面也要加上,
列表中的元素可以是 数字、字符串、布尔值、列表(列表的嵌套)
复制列表:
a = [1,2,3]
b = a[:] #[:]是复制列表
print(a,b)
1.查 切片:
list[1:] #从1开始取到最后
list[1:-1] #从1开始取到倒数第二值
list[1:-1:1] #从左到右一个一个去取,取到倒数第二值
list[1::2] #左到右隔一个去取
list[3::-1] #从3开始从右到左一个一个取,注意索引值不变
切片器详解:
str[a:b:c]
a表示切片开始的索引位置
b表示切片结束的索引位置
a,b参数都可正可负
a,b为正数的时候,左边第一个内容索引为0
a,b为负数的时候,右边第一个内容索引为1
参数c表示从左到右(c=1)或者从右到左(c=-1)
str = 'onetwothree' #打印字符串倒数后两位的值 val = str[-1:-3:-1] print(val) #打印结果:ee
2.增 添加:
2.1:append()
append(“str”)将数据插到最后一个位置
代码示例:
list = ["one","two",3,4,"five"]
list.append("six")
print(list)
输出结果:
['one', 'two', 3, 4, 'five', 'six']
append()注意事项:
1 list1 = [11,22,33]
2 val = list1.append(44)
3 print(val)
4 #这里返回的是None,对于列表来说,执行方法之后改变的是原来的值,变量接收不到
2.2:insert()
根据索引值位置将数据插入到任意一个位置
代码示例:
list = ["one","two",3,4,"five"]
list.insert(2,"two2") #想把新对象插在什么位置就输入相应的索引值
print(list)
输出结果:
['one', 'two', 'two2', 3, 4, 'five']
3.改 修改:
想要修改首先得用切片把相应的值取出来,在进行赋值即可。
代码示例:
list = ["one","two",3,4,"five"]
list[1] = 2 #将索引值为1的对象取出来,再重新赋值
print(list)
输出结果:
['one', 2, 3, 4, 'five']
需求:将list = ["one","two",3,4,"five"]这个列表里的two 和 4 修改成 2 和 four
代码示例:
list = ["one","two",3,4,"five"]
list[1:4:2] = [2,"four"]
print(list)
输出结果:
['one', 2, 3, 'four', 'five']
注意:在list[1:4:2] = [2,"four"]中,因为list[1:4:2]输出得是一个列表,所以等号右边也必须是个列表
4.删 删除:
4.1:remove
remove只能删除一个,并且()里填写的是对象内容
代码示例:
list = ["one","two",3,4,"five"]
list.remove("two") #删除two
print(list)
输出结果:
['one', 3, 4, 'five']
4.2 :pop
pop删除的时候()里是填写索引值,并且还可以将删除数据返回出来,如果括号里面不填索引值,即pop(),则默认删除最后一个值。
代码示例:
list = ["one","two",3,4,"five"]
a = list.pop(1) #删除 two
print(list,a)
输出结果:
['one', 3, 4, 'five'] two
4.3 :del什么都可以删除
代码示例:
list = ["one","two",3,4,"five"]
del list[0] #删除 one
print(list)
输出结果:
['two', 3, 4, 'five']
5.列表的其他操作
5.1 :count:计算某元素出现次数
代码示例:
list = ["one","two",3,4,"five"]
v = list.count("two") #计算two出现的次数
print(v)
输出结果:1
5.2:extend:用于在列表末尾一次性追加另一个序列中的多个值,括号中必须是可迭代对象,可以理解为批量的append()
代码示例:
a = [1,2,3]
b = [4,5,6]
a.extend(b) #把b加到a里面
print(a)
print(b)
输出结果:
[1, 2, 3, 4, 5, 6]
[4, 5, 6]
5.3:index根据内容找位置,输出得是第一个匹配内容的索引位置
代码示例:
list = ["one","two",3,4,"five"]
T = list.index("five") #查找five的索引值
print(T)
输出结果:4
5.4 合集
1.reverse:用于反向列表中元素
2.sort:对原列表进行排序
reverse -- 排序规则,reverse = True 降序(由大到小), reverse = False 升序(由小到大)(默认)
3.in:查一个数据在不在列表内
4.type:身份判断:判断一个对象是不是列表
代码示例:
list0 = ["one","two",str(3),str(4),"five"]
list0.reverse() #反向列表中元素
print(list0)
list0.sort(reverse=True) #由大到小de对原列表进行排序
print(list0)
a = "six" in list0 #判单six在不在列表里
print(a)
b = type(list0) is list #判断list0是不是列表
print(b)
输出结果:
['five', '4', '3', 'two', 'one']
['two', 'one', 'five', '4', '3']
False
True
6.列表练习题:
list = ["one","two",3,4,"five","天才"]
把list列表中的天才的 天 改成 蠢
代码示例:
list = ["one","two",3,4,"five","天才"]
v = list[5].replace("天","蠢")
list[5] = v
print(list)
输出结果:['one', 'two', 3, 4, 'five', '蠢才']
注意:字符串不能通过索引值修改,只能通过索引值取出来。(⬇)
7.补充:
需求:索引为奇数值,删除
注意:删除列表元素时,会影响列表长度,从而使得索引取值时,容易出现错误。
li = [11,22,33,44,66]
# 解决方案一:
li = [11, 22, 33, 44, 66] # 0
new_list = []
for i in range(0,len(li)):
if i%2 == 0:
new_list.append(li[i])
li = new_list
print(li)
# 解决方案二:
li = [11, 22, 33, 44, 66] # 0
for i in range(len(li)-1,-1,-1): # 4,0
if i%2 == 1:
del li[i]
print(li)
#解决方案三:切片+步长
li = [11, 22, 33, 44, 66]
del li[0:4:2]
print(li)
需求:将[1,3,5]中的每个元素平方
正常思路:
new_list = []
for i in [1,3,5]:
new_list.append(i*i)
print(new_list) #输出结果:[1, 9, 25]
列表推导式:以[ ]框住里面的内容
print([i*i for i in [1,3,5]]) #输出结果:[1, 9, 25]
列表推导式图示流程:
可以看出列表推导式的作用就是简化代码
列表推导式例题:
1.输出10以内能被三整除的数的平方
print([i*i for i in range(10) if i %3 == 0]) #[0, 9, 36, 81]
2.输出列表每一个包含‘o’元素的字符串
list_case = [['one','two','three'],['four','five','six']]
正常思路:
list_case = [['one','two','three'],['four','five','six']]
for i in list_case:
for v in i:
if v.count('o')>0:
print(v)
列表推导式:
list_case = [['one','two','three'],['four','five','six']]
print([v for i in list_case for v in i if v.count('o')>0])
Python 的元组与列表类似,不同之处在于元组的元素不能修改。
元组使用小括号,列表使用方括号。
元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。
1. 创建空元组
tup1 = ()
2. 元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:
代码示例:
tup1 = (50) print(type(tup1)) # 不加逗号,类型为整型 tup1 = (50,) print(type(tup1)) # 加上逗号,类型为元组
输出结果:<class 'int'>、<class 'tuple'>
3. 元组可以使用下标索引来访问元组中的值
4. 可以对元组进行连接组合
5.元组可以计算长度len()
6.元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组
7.重点:
元组的儿子不能修改,但是孙子可以,元组的元素不能修改,但如果元组的元素不是元组类型的话,那么元组的元素的元素是可以修改的。
代码示例:
tuple1 = ("one","two","three",[1,2,"zrh"],(1,2,3),"four") tuple1[3][1] = 3 print(tuple1) tuple1[3].append("q") print(tuple1)
输出结果:
('one', 'two', 'three', [1, 3, 'zrh'], (1, 2, 3), 'four')
('one', 'two', 'three', [1, 3, 'zrh', 'q'], (1, 2, 3), 'four')
字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值(key=>value)对,用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中
键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变类型。
不可变类型:整型、字符串、元组
可变类型:字典、列表
格式:变量名 = {键:值,键:值}
代码示例:
dict1 = {
"name":"zrh",
"age":20,
"height":75
}
1.:dict.get
1.1通过键取值
代码示例:
dict1 = { "name":"zrh", "age":20, "height":75 } print(dict1.get("name"))
输出结果:zrh
1.2()参数,如果键不存在,就用后面的结果当作默认值。
代码示例:
dict1 = { "name":"zrh", "age":20, "height":75 } print(dict1.get("key",999))
输出结果:999
2.:dict.keys() 、 dict.values() and dict.items()
经常和for循环一起使用
字典在for循环的时候尽量不要用两个变量去分别接收 键 和 值,这样会造成内存负荷过大,可以先遍历键,然后通过键去找值
代码示例:
dict1 = { "name":"zrh", "age":20, "height":75 } a = dict1.keys() #查看所有键 print(type(a)) #查看a的类型 print(a) print(dict1.values()) #查看所有值 print(dict1.items()) #查看所有键值对
输出结果:
<class 'dict_keys'>
dict_keys(['name', 'age', 'height'])
dict_values(['zrh', 20, 75])
dict_items([('name', 'zrh'), ('age', 20), ('height', 75)])
for循环注意事项:
dict1 = {} for key in dict1: pass for key in dict1.items(): pass for key in dict1.keys(): pass for key in dict1.values(): pass
注意dict1后面括号的有无
3.增加键值对
代码示例:
dict1 = { "name":"zrh", "age":20, "height":75 } dict1["hobby"] = "eat" print(dict1)
输出结果:{'name': 'zrh', 'age': 20, 'height': 75, 'hobby': 'eat'}
如果增加的键已经存在,那就是改的功能。
4.删除
代码示例:
dict1 = { "name":"zrh", "age":20, "height":75 } del dict1["name"] #删除指定键值对 print(dict1) dict1.clear() print(dict1) #清空字典中所有键值对,但空字典还存在 dict2 = { "name":"zrh", "age":20, "height":75 } a = dict2.pop("name") #通过键去删除,并可以返回相应的值 print(a) print(dict2) b = dict2.popitem() print(b) print(dict2) #随机删除一对键值对,并且返回相相应键值对
输出结果:
{'age': 20, 'height': 75}
{}
zrh
{'age': 20, 'height': 75}
('height', 75)
{'age': 20}
5.嵌套
字典里面可嵌套字典或者列表都可以,列表页都可以嵌套字典。
在修改时,遇到字典用键,遇到列表用索引值,然后查找出来之后赋值即可,其他操作一样,反正一句话:
遇到字典用键,遇到列表用索引值。
6.update()用于将括号中的键值对添加到目标对象中,如果括号中的键在目标对象中存在,则更新目标对象的值
1 dict1 = {
2 'k1':'v1',
3 'k2':'v2',
4 'k3':'v3'
5 }
6 dict1.update({'k4':'v4','k1':'v11'})
7 print(dict1)
8 #输出结果:{'k1': 'v11', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4'}
7.fromkeys()创建字典
1 #fromkeys使用的时候不是文件名. 是用dict.来调用
2 val = dict.fromkeys(['k1','k2','k3'],666) #将666作为值赋给K1 K2 K3三个键
3 print(val) #输出结果{'k1': 666, 'k2': 666, 'k3': 666}
4 val['k1'] = 999 #给数字重新赋值,在内存中重新开辟一块内存用来储存999,然后k1指向999,原来的k2 k3值不变
5 print(val) #输出结果{'k1': 999, 'k2': 666, 'k3': 666}
6
7 val = dict.fromkeys(['k1','k2','k3'],[])
8 val['k1'].append(666)
9 val['k2'].append(999)
10 #k1 k2 k3指向的是同一个值,即[],每次往里加内容的时候 k1 k2 k3 的值都会发生变化
11 print(val) #输出结果{'k1': [666, 999], 'k2': [666, 999], 'k3': [666, 999]}
12
13 val = dict.fromkeys(['k1','k2','k3'],[])
14 val['k1'].append(666)
15 val['k1'] = [1,2,3] #这里是重新赋值操作,在内存中重新开辟一块空间储存[1,2,3],k1指向他,k2 k3值不变
16 print(val) #输出结果{'k1': [1, 2, 3], 'k2': [666], 'k3': [666]}
8.补充
# 题:dic = {'k1':"v1",'k2':'v2'}把key="k1",键值对删除
del dic['k1']
# 题:dic = {'u1':"v1",'k2':'v2','k3':'v3'}把key中存在k,键值对删除
dic = {'u1':"v1",'k2':'v2','k3':'v3'}
# 不要在循环当前字典的过程中,修改当前字典大小
错误方式:
for key in dic:
if 'k' in key:
del dic[key]
正确方式 :
dic_key_list = []
for key in dic:
dic_key_list.append(key)
for row in dic_key_list:
if 'k' in row:
del dic[row]
print(dic)
集合(set)是一个无序的不重复元素序列。
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
1 list1 = [] #等价于list1 = list()
2 tuple1 = () #等价于tuple1 = tuple()
3 dict1 = {} #等价于dict1 = dict()
4 #所以创建集合是 set()
集合里的元素必须是不可变的
set1 = {“1”,“zrh”,[1,2,3]}这样就会报错,因为列表是可变的
不可变类型:整型、字符串、元组
可变类型:字典、列表
集合也可以for循环,集合不可以通过索引来取值,因为集合无序。
创建格式:
1 parame1 = {"one","two","three"} #创建方法1
2 a = set("apple") #创建方法2
3 print(parame1,a)
4 #打印结果{'two', 'three', 'one'}集合无序的;
5 #{'l', 'p', 'a', 'e'}因为是不能重复的,所以只有一个a
Set内置方法:
方法 |
描述 |
add() |
为集合添加元素(无返回值) |
clear() |
移除集合中的所有元素(无返回值) |
copy() |
拷贝一个集合(无返回值) |
difference() |
返回多个集合的差集(返回一个新的集合) |
difference_update() |
方法用于移除两个集合中都存在的元素(无返回值) |
discard() |
删除集合中指定的元素(无返回值)删除元素不存在不会报错 |
intersection() |
返回集合的交集(返回一个新的集合) |
intersection_update() |
更新指定集合为指定集合和参数集合的交集(无返回值) |
isdisjoint() |
判断两个集合是否无交集,如果没有返回 True,否则返回 False(返回布尔值 ) |
issubset() |
判断指定集合是否为该方法参数集合的子集(返回布尔值 ) |
issuperset() |
判断该方法的参数集合是否为指定集合的子集(返回布尔值 ) |
pop() |
随机移除元素(返回移除的元素) |
remove() |
移除指定元素(返回移除的元素)删除的元素不存在会报错 |
symmetric_difference() |
返回两个集合中不重复的元素集合(返回一个新的集合) |
symmetric_difference_update() |
移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中(无返回值) |
union() |
返回两个集合的并集(返回一个新的集合) |
update() |
给集合添加元素(无返回值)
|
Set内置方法部分应用举例:
#1.add() 添加 参数必须是字符串
name = {'one','two','three','four','five'}
a = name.add('six') #括号内的元素只能填一个,并且要维护集合元素永不重复
print(a) #输出结果:None 说明add不可返回值,直接修改的是集合
print(name) #输出结果:{'four', 'five', 'three', 'six', 'one', 'two'}
#2.update() 添加更新 参数可以是列表,元组,字典,集合等
name = {'one','two','three','four','five'}
a = name.update(['six','seven'])
print(a) #输出结果:None 说明update不可返回值,直接修改的是集合
print(name) #输出结果:{'three', 'seven', 'four', 'six', 'one', 'two', 'five'}
#3. difference() 用于计算差集
#difference() 方法用于返回集合的差集,即返回的集合元素包含在第一个集合中,但不包含在第二个#集合(方法的参数)中。
name = {'one','two','three','four','five'}
name1 = {'five','six','seven'}
a = name.difference(name1) #name中存在,name1中不存在,创建新变量,name name1值不变
print(a) #输出结果:{'three', 'four', 'one', 'two'}
#4. difference_update() 方法用于移除两个集合中都存在的元素。
#difference_update() 方法与 difference() 方法的区别在于 difference() 方法返回一个移除相同元素的新集合,
而 difference_update() 方法是直接在原来的集合中移除元素,没有返回值。
name = {'one','two','three','four','five'}
name1 = {'five','six','seven'}
a = name.difference_update(name1) #在name中删除name1中存在的值
print(a) #输出结果:None 没有返回值
print(name) #输出结果:{'four', 'two', 'three', 'one'}
快速去重:利用集合元素不重复的方法
name = ['one','two','five','three','four','five']
val = set(name) #将列表转换为集合格式
print(val) #{'four', 'two', 'five', 'one', 'three'}
set集合也可以进行> < 的比较:
#判断b是不是a集合的子集
a = {1,2,3,4,5}
b = {4,5}
print(a>b)
# 结果为True
a = {1,2,3,4,5}
b = {1,2,3,4,5}
print(a1!=b) !=不等于的意思
#结果为False,代表a,b两个集合相同
文件操作三要素:
1. 路径:D:\\name.txt
2. 编码:utf-8或gbk等
3. 模式:
x |
写模式,新建一个文件,如果该文件已存在则会报错。 |
b |
二进制模式。即bytes |
+ |
打开一个文件进行更新(可读可写)。 |
r |
以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb |
以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
r+ |
打开一个文件用于读写。文件指针将会放在文件的开头。常用 |
rb+ |
以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
w |
打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb |
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
w+ |
打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ |
以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
a |
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ |
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
1.只读模式r:
obj = open('D:\\name.txt',encoding='utf-8',mode='r') #\\中的第一个\表示转义符
# 文件路径 编码格式 模式
content = obj.read() #此时的content是str类型,str在内存上又是Unicode类型
# 所以mode = 'r' python内部会把utf-8数据转换成Unicode类型
obj.close()
obj = open('D:\\name.txt',mode='rb')
# 文件路径 模式
content = obj.read() #此时的content是bytes类型,打印出来是bytes的表现形式
obj.close()
总结:
1.文件在硬盘上存储一定是UTF-8或者GBK等编码的01
2.rb=原封不动的拿数据,数据此时是某种编码的01,为了显示方便,便会显示bytes的表现形式
3.r=内部会有转换,但是必须记住要加编码格式encoding = ‘utf-8’等
4.encoding是文件之前用什么编码保存,就用什么编码打开
5.一般情况下mode = ‘rb’,用bytes的很少,一般用于上传,下载文件时才用到
只写模式w:
写之前会清空里面的内容再写
1.open(文件路径,mode='wb')
count = open('name.txt',mode='wb')
count.write("dooble".encode('utf-8'))
#wb模式下,往里存的必须是utf-8等编码格式,字符串默认是Unicode,所以要转换成utf-8
count.close()
2.open(文件路径,mode='w',encoding='utf-8')
count = open('name.txt',encoding='utf-8',mode='w')
count.write('123') #会先清空,再写,只能写不能读
count.close()
3.writelines() 将列表的内容写入文件,参数是个列表
只追加模式a:
追加模式不清空原来文件的内容
1.open(文件路径,mode='ab')
count = open('name.txt',mode='a',encoding='utf-8')
count.write("name1")
count.close()
2.open(文件路径,mode='a',encoding='utf-8')
count = open('name.txt',mode='ab')
count.write("name1".encode('utf-8'))
#ab模式下,往里存的必须是utf-8等编码格式,字符串默认是Unicode,所以要转换成utf-8
count.close()
r+模式:
count = open('name.txt',mode='r+',encoding='utf-8') #r+可读可写 w+可写可读,写之前会清空原文件内容,读的是你写的内容
#此时指针在第一个位置,不跳指针继续写会从第一个位置覆盖
count.write("name1") #这样就直接覆盖了
count.read() #读到最后,指针此时在最后了
count.write("name1") #指针在最后,于是就添加到最后了
#要想在第二个位置覆盖,那需要调整指针
count.seek(0) #将指针调整到0位置
count.write("2") #此时2就覆盖了原来在0位置的内容
count.close() #关闭文件
r+模式注意事项:
file文件内容:
注意事项一:
with open("file",'r+',encoding='utf-8') as file_1: #打开文件时候不清空文件
file_1.readline() #读第一行,指针现在在第一行末尾
file_1.write("good") #在执行写操作的时候,是在文件末尾追加
输出结果:
注意事项二:
当不执行读操作的时候,再写的话默认从开始的位置覆盖
with open("file",'r+',encoding='utf-8') as file_1: #打开文件时候不清空文件
file_1.write("good") #当不执行读操作的时候,再写的话默认从开始的位置覆盖
输出结果:
所以在以后的操作中,不要同时读写操作一个文件,因为会乱,所以不用“R+”,就单独的用 r、w、a
文件的功能:
read
obj = open('美女.txt',mode='r+',encoding='utf-8')
data = obj.read() # 读取所有文件内容
data = obj.read(2) # 在r模式中读取的2是2个字符;在rb模式中读取的2是2个字节
obj.write('字节或字符串')
seek
obj = open('美女.txt',mode='r+',encoding='utf-8') #打开文件时注意该文件是不是用utf-8编码的
obj.seek(2) # 参数2永远是字节,用来指定指针的位置 utf-8一个中文3个字节
tell等
obj.tell() # 读取当前指针的位置,读取到的是字节数
obj.writable() #是否可写,r模式下就不可写,可以用变量接收返回值
obj.readable() #是否可读,w模式下就不可读,可以用变量接收返回值
flush将内存中内容刷到硬盘
count = open('name.txt',mode='r+',encoding='utf-8')
while True:
val = input(">>>")
count.write(val) #给文件里写内容
count.flush() #强行把内容刷到硬盘,不然文件在循环里永远关闭不了
count.close()
readline()从文本文件中读取一行内容作为结果返回,结果为字符串类型
file_name文件内容:
with open('file_name','r',encoding='utf-8') as file: val = file.readline() print(type(val)) print(val) # 在读第二行的时候,第一行内容是 君不见黄河之水天上来\n,其中的\n也会被读出来,所以打印的时候中间会多一行间隙 val = file.readline() print(val)
输出结果:
readline常用的一种方法:
with open('file_name','r',encoding='utf-8') as file: for line in file: print(line) ##即使文件有80个G,for循环的垃圾回收体制会即时节省内存
readlines()将文本文件中的每行文本作为一个字符串存入列表中,返回该列表,对于大文件会占很多内存,不建议使用
truncate()
obj.truncate() #截取文件内容,根据指针位置,只保留指针之前数据
注意:写文件的时候一定记着关闭文件,这里有一种自动关闭的方法:
with open("name.txt",mode="r+",encoding="utf-8") as count: #as 后面是接收打开文件对象的变量名
#在缩进里写代码内容
#等待运行完代码后会自动跳出缩进,就自动关闭了
总结:
with open("file",'r+',encoding='utf-8') as file_1: #打开文件时候不清空文件 pass import os os.remove('file') #删除file的文件 os.rename('file','file_new') #将文件名file修改为file_new
文件内容的修改:
步骤:
1.先遍历文件
2.str.replace或者str.split
3.将修改后的所有文件重新写入一个新文件
4.删除原来文件
5.将新文件重命名为原来文件的名字
举例:
file文件的内容:
需求1:给每一项的第一个 | 前的字母加上 _good
import os #导入os模块
file_2 = open("file_new",'w',encoding='utf-8') #以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容
with open("file",'r',encoding='utf-8') as file_1: #以读模式打开file文件
for line in file_1:
list_1 = line.split("|")
list_1[0] = list_1[0]+"_good"
content = '|'.join(list_1)
file_2.write(content) #每遍历一个内容,修改后就写到file_new里面
file_2.close()
os.remove('file') #删除原来的file文件
os.rename('file_new','file') #将file_new文件重命名为file
输出结果:
需求2:给zcx后面加上 _good ,其他保持不变
import os #导入os模块
file_2 = open("file_new",'w',encoding='utf-8') #以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容
with open("file",'r',encoding='utf-8') as file_1: #以读模式打开file文件
for line in file_1:
list_1 = line.split("|")
if list_1[0] == 'zcx': #判断是不是zcx
list_1[0] = list_1[0]+"_good"
content = '|'.join(list_1)
file_2.write(content) #每遍历一个内容,修改后就写到file_new里面
file_2.close()
os.remove('file') #删除原来的file文件
os.rename('file_new','file') #将file_new文件重命名为file
输出结果:
Json文件解析:
Json本质上是—种嵌套字典格式,但键所对应的值,往往更加复杂,不仅是数字,还可以是字符串,数组,列表等
import json with open('F:\pycharm\data\case.json',mode='r',encoding='utf-8-sig') as file: file_case = file.read() print(type(file_case)) #<class 'str'> data = json.loads(file_case) #将file_case文件解析成json格式,参数的对应的文件内容必须是字符串格式 print(type(data)) #<class 'dict'> print(data) with open('F:\pycharm\data\case_write.json',mode='w',encoding='utf-8') as filr: json.dump(data,filr,indent=0) #将data数据写入到filr对应的json文件里,indent=0表示空格为0
1.变量指向:
name = "zrh"
name1 = name
print(name,name1)
name = "zrh1"
print(name,name1)
#输出结果
#zrh zrh
#zrh1 zrh
内部原理:
name1通过name指向zrh,此时name1的值就是zrh后面即使name改变为zrh1,name1的值也不会改变。
2.列表指向:
list1 = [1,2,3]
list2 = list1
list1.append(4)
print(list1,list2)
#输出结果:[1, 2, 3, 4] [1, 2, 3, 4]
内部原理:
list2通过list1指向【1,2,3】,此时list2的值就是【1,2,3】,append直接改变的是值,所以list1和list2都改变了。
3.深浅拷贝
浅拷贝:只拷贝第一层,其他都指向同一数据
深拷贝:不管里面有多少嵌套,都会拷贝下来
深浅拷贝只有存在嵌套时才会有异同
内存原理:
公式格式:
list1 = [1,[2,3],4]
#浅拷贝
list2 = list1.copy()
#深拷贝
import copy
list3 = copy.deepcopy(list1)
注意:
list3最后一层是python为了节省内存才直接指向list1的数据,所以list1改变数据,是从新开辟出一块新的内存让list1指向,list3不变。
list1 = [1,[2,3],4]
#深拷贝
import copy
list3 = copy.deepcopy(list1)
list1[0] = 0
print(list3[0])
#输出结果: 1