计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用8位来表示(一个字节),即:2**8=256,所以,ASCII码最多只能表示256个符号
ascii用1个字节代表一个字符;
unicode常用2个字节代表一个字符,生僻字需要用4个字节;
UTF-8英文字母被编码成1个字节,汉字通常是3个字节有很生僻的字符才会被编码成4-6个字节。
字母x,用ascii表示是十进制的120,二进制01111000
汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的0100111000101101。
字母x,用unicode表示二进制0000000001111000,所以unicode兼容ascii,也兼容万国,是世界的标准
这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:
字符
Ascll
Unicode
Utf-8
x
01000001
0000000001000001
中
不能表示
0100111000101101
111001001011100010101101
从上面的表格还可以发现,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个字节
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(可变长,全称UnicodeTransformationFormat),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存。
二.Python字符串格式化
Python支持格式化字符串的输出。尽管这样可能会用到非常复杂的表达式,但最基本的用法是将一个值插入到一个有字符串格式符%s的字符串中。
格式输出汇总:
1#第一种2val="我叫%s,今年%d岁,身高%d"%('zrh',20,175)3print(val)#运行结果:我叫zrh,今年20岁,身高1754#第二种5val="我叫{0},今年{1}岁,身高{2},我弟弟身高也是{2}"6val1=val.format("zrh",20,175)7print(val1)#运行结果:我叫zrh,今年20岁,身高175,我弟弟身高也是1758#第三种9v=input("yourname:")#用户输入姓名10val="我叫{name},今年{age}岁,身高{height}"11val1=val.format(name=v,age="20",height="175")#name=v是用户输入的那个姓名12print(val1)13#第四种14val="我叫{name},今年{age}岁"15dic1={"name":"zrh","age":20}16val1=val.format(**dic1)17print(val1)18#第五种19name="我叫{name},年龄{age}"20val=name.format_map({'name':'海角','age':18})#只有一种写法,里面必须是字典21print(val)如果在格式化输出中想要输出%号,就要用到%%格式
print("我是%s,我的进度已经完成80%%"%('zrh'))输出结果:
我是zrh,我的进度已经完成80%
%06d表示数字用6位表示,数字不足6位的话用0代替
frommathimport*a=log(e**2)print('%.2f'%(a))#输出结果:2.00百分号的输出:
num=0.1print("数据比例为%.2f%%"%(num*100))#输出结果:数据比例为10.00%变量名关键字:
python在定义变量名时区分大小写
\t表空格
\n表换行
如果字符串中需要输出\n、\t等,需要加两个\\
print("\\n")#输出结果\n如果字符串中需要输出的“\”非常多的话,可以使用原始字符串模式打印,即在字符串前输入r
如果字符串超过一行,再给变量赋值时需要使用三引号
case='''超过一行的字符串'''运算问题:
%取余
\\整除
取余的原理
整除的原理:结果向下取整
三.进制转换
进制也就是进制位,我们常用的进制包括:二进制、八进制、十进制与十六进制,它们之间区别在于数运算时是逢几进一位。比如二进制是逢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=1int类
Booleanvalue(布尔值)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=16v=count.bit_length()print(v,"---",count)输出结果:
5---16
注意:
count="1"count1="2"print(count+count1)#输出结果:12字符串的加法是拼接的作用count2=1count3=2print(count2+count3)#输出结果:3数字的加法是加法作用#需求,输入一个数字,然后每个数字相加,列入输入152,结果就是1+5+2count4="152"#在数字和字符串中只有字符串才可以遍历,所以要把count4转为str类型val=0foriinrange(len(count4)):val+=int(count4[i])#count4[i]是字符串,所以要转为数字才能相加print(val)浮点数:
2.str类
对于字符串,执行内置命令后,原来的值不变。
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开始计算不是从1content="人生自古谁无死,早死晚死都得死"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="good1night2"a.isdecimal()#如果a中只有十进制字符,则返回True,否则为Falsea.isdigit()#如果a中的所有字符都是数字,并且在S中至少有一个字符,则返回Truea.isnumeric()#如果a中只有数字字符,则返回True,否则为False2.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=1flase=0
4.字符串转布尔值bool(对象)
bool(“”)是False
其他任何字符串都是True
a=9or2>3print(a)输出结果:9
a=0or2>3print(a)输出结果:False
a=0or6print(a)输出结果:6
a=0or2<3print(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)六、For循环
Pythonfor循环可以遍历任何序列的项目,如一个列表或者一个字符串。
for循环的一般格式如下:
for变量接收名in对象:
list1=["one","two","three",4]foriinlist1:print(i)输出结果:
one
two
three
4
For循环时加上序号enumerate:
list1=["手机","电脑","ipad"]fori,vinenumerate(list1,1):#表示遍历list1这个列表,序号从1开始。print(i,v)输出结果:
1手机
2电脑
3ipad
循环语句可以有else子句,它在穷尽列表(以for循环)或条件变为false(以while循环)导致循环终止时被执行,但循环被break终止时不执行,简而言之就是break后不会执行下级的else(注意break的级别)
range()函数
如果你需要遍历数字序列,可以使用内置range()函数,它会生成数列
range(起始值,终止值,步长)这里是左闭右开区间,可以取到起始值,但是取不到终止值,只能取到终止值的前一个,步长就是遍历时的距离,默认是1
foriinrange(5,1,-1):print(i)输出结果:
5
3
2
range的组和用法:
可以结合range()和len()函数以遍历一个序列的索引:
list1=["手机","电脑","ipad"]foriinrange(len(list1)):#len是从1开始,range没写参数是从0开始print(i,list1[i])输出结果:
0手机
1电脑
2ipad
print会自动在行末加上回车,如果不需回车,只需在print语句的结尾添加一个逗号,并设置分隔符参数end,就可以改变它的行为。
七、三元运算
a=1b=2ifa a=1b=2c=bifa 八.列表 列表是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)#打印结果:ee2.增添加: 2.1:append() append(“str”)将数据插到最后一个位置 list=["one","two",3,4,"five"]list.append("six")print(list)输出结果: ['one','two',3,4,'five','six'] append()注意事项: 1list1=[11,22,33]2val=list1.append(44)3print(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")#删除twoprint(list)输出结果: ['one',3,4,'five'] 4.2:pop pop删除的时候()里是填写索引值,并且还可以将删除数据返回出来,如果括号里面不填索引值,即pop(),则默认删除最后一个值。 list=["one","two",3,4,"five"]a=list.pop(1)#删除twoprint(list,a)输出结果: ['one',3,4,'five']two 4.3:del什么都可以删除 list=["one","two",3,4,"five"]dellist[0]#删除oneprint(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"inlist0#判单six在不在列表里print(a)b=type(list0)islist#判断list0是不是列表print(b)输出结果: ['five','4','3','two','one'] ['two','one','five','4','3'] True 6.列表练习题: list=["one","two",3,4,"five","天才"] 把list列表中的天才的天改成蠢 list=["one","two",3,4,"five","天才"]v=list[5].replace("天","蠢")list[5]=vprint(list)输出结果:['one','two',3,4,'five','蠢才'] 注意:字符串不能通过索引值修改,只能通过索引值取出来。() 7.补充: 需求:索引为奇数值,删除注意:删除列表元素时,会影响列表长度,从而使得索引取值时,容易出现错误。 li=[11,22,33,44,66]#解决方案一:li=[11,22,33,44,66]#0new_list=[]foriinrange(0,len(li)):ifi%2==0:new_list.append(li[i])li=new_listprint(li)#解决方案二:li=[11,22,33,44,66]#0foriinrange(len(li)-1,-1,-1):#4,0ifi%2==1:delli[i]print(li)#解决方案三:切片+步长li=[11,22,33,44,66]delli[0:4:2]print(li)九、列表推导式 需求:将[1,3,5]中的每个元素平方 正常思路: new_list=[]foriin[1,3,5]:new_list.append(i*i)print(new_list)#输出结果:[1,9,25]列表推导式:以[]框住里面的内容 print([i*iforiin[1,3,5]])#输出结果:[1,9,25]列表推导式图示流程: 可以看出列表推导式的作用就是简化代码 列表推导式例题: 1.输出10以内能被三整除的数的平方 print([i*iforiinrange(10)ifi%3==0])#[0,9,36,81]2.输出列表每一个包含‘o’元素的字符串 list_case=[['one','two','three'],['four','five','six']] list_case=[['one','two','three'],['four','five','six']]foriinlist_case:forvini:ifv.count('o')>0:print(v)列表推导式: list_case=[['one','two','three'],['four','five','six']]print([vforiinlist_caseforviniifv.count('o')>0])十、元组 Python的元组与列表类似,不同之处在于元组的元素不能修改。 元组使用小括号,列表使用方括号。 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。 1.创建空元组 tup1=()2.元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用: tup1=(50)print(type(tup1))#不加逗号,类型为整型tup1=(50,)print(type(tup1))#加上逗号,类型为元组输出结果: 3.元组可以使用下标索引来访问元组中的值 4.可以对元组进行连接组合 5.元组可以计算长度len() 6.元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组 7.重点: 元组的儿子不能修改,但是孙子可以,元组的元素不能修改,但如果元组的元素不是元组类型的话,那么元组的元素的元素是可以修改的。 tuple1=("one","two","three",[1,2,"zrh"],(1,2,3),"four")tuple1[3][1]=3print(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()anddict.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())#查看所有键值对输出结果: dict_keys(['name','age','height']) dict_values(['zrh',20,75]) dict_items([('name','zrh'),('age',20),('height',75)]) for循环注意事项: dict1={}forkeyindict1:passforkeyindict1.items():passforkeyindict1.keys():passforkeyindict1.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}deldict1["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} {} ('height',75) {'age':20} 5.嵌套 字典里面可嵌套字典或者列表都可以,列表页都可以嵌套字典。 在修改时,遇到字典用键,遇到列表用索引值,然后查找出来之后赋值即可,其他操作一样,反正一句话: 遇到字典用键,遇到列表用索引值。 6.update()用于将括号中的键值对添加到目标对象中,如果括号中的键在目标对象中存在,则更新目标对象的值 1dict1={2'k1':'v1',3'k2':'v2',4'k3':'v3'5}6dict1.update({'k4':'v4','k1':'v11'})7print(dict1)8#输出结果:{'k1':'v11','k2':'v2','k3':'v3','k4':'v4'}7.fromkeys()创建字典 1#fromkeys使用的时候不是文件名.是用dict.来调用2val=dict.fromkeys(['k1','k2','k3'],666)#将666作为值赋给K1K2K3三个键3print(val)#输出结果{'k1':666,'k2':666,'k3':666}4val['k1']=999#给数字重新赋值,在内存中重新开辟一块内存用来储存999,然后k1指向999,原来的k2k3值不变5print(val)#输出结果{'k1':999,'k2':666,'k3':666}67val=dict.fromkeys(['k1','k2','k3'],[])8val['k1'].append(666)9val['k2'].append(999)10#k1k2k3指向的是同一个值,即[],每次往里加内容的时候k1k2k3的值都会发生变化11print(val)#输出结果{'k1':[666,999],'k2':[666,999],'k3':[666,999]}1213val=dict.fromkeys(['k1','k2','k3'],[])14val['k1'].append(666)15val['k1']=[1,2,3]#这里是重新赋值操作,在内存中重新开辟一块空间储存[1,2,3],k1指向他,k2k3值不变16print(val)#输出结果{'k1':[1,2,3],'k2':[666],'k3':[666]}8.补充 #题:dic={'k1':"v1",'k2':'v2'}把key="k1",键值对删除deldic['k1']#题:dic={'u1':"v1",'k2':'v2','k3':'v3'}把key中存在k,键值对删除dic={'u1':"v1",'k2':'v2','k3':'v3'}#不要在循环当前字典的过程中,修改当前字典大小错误方式:forkeyindic:if'k'inkey:deldic[key]正确方式:dic_key_list=[]forkeyindic:dic_key_list.append(key)forrowindic_key_list:if'k'inrow:deldic[row]print(dic)十二、集合set 集合(set)是一个无序的不重复元素序列。 可以使用大括号{}或者set()函数创建集合,注意:创建一个空集合必须用set()而不是{},因为{}是用来创建一个空字典。 1list1=[]#等价于list1=list()2tuple1=()#等价于tuple1=tuple()3dict1={}#等价于dict1=dict()4#所以创建集合是set()集合里的元素必须是不可变的 set1={“1”,“zrh”,[1,2,3]}这样就会报错,因为列表是可变的 集合也可以for循环,集合不可以通过索引来取值,因为集合无序。 创建格式: 1parame1={"one","two","three"}#创建方法12a=set("apple")#创建方法23print(parame1,a)4#打印结果{'two','three','one'}集合无序的;5#{'l','p','a','e'}因为是不能重复的,所以只有一个aSet内置方法: 方法 描述 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内置方法部分应用举例: #判断b是不是a集合的子集a={1,2,3,4,5}b={4,5}print(a>b)#结果为Truea={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.模式: 写模式,新建一个文件,如果该文件已存在则会报错。 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-8count.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-8count.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文件内容: 注意事项一: withopen("file",'r+',encoding='utf-8')asfile_1:#打开文件时候不清空文件file_1.readline()#读第一行,指针现在在第一行末尾file_1.write("good")#在执行写操作的时候,是在文件末尾追加输出结果: 注意事项二: 当不执行读操作的时候,再写的话默认从开始的位置覆盖 withopen("file",'r+',encoding='utf-8')asfile_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')whileTrue:val=input(">>>")count.write(val)#给文件里写内容count.flush()#强行把内容刷到硬盘,不然文件在循环里永远关闭不了count.close()readline()从文本文件中读取一行内容作为结果返回,结果为字符串类型 file_name文件内容: withopen('file_name','r',encoding='utf-8')asfile:val=file.readline()print(type(val))print(val)#在读第二行的时候,第一行内容是君不见黄河之水天上来\n,其中的\n也会被读出来,所以打印的时候中间会多一行间隙val=file.readline()print(val)输出结果: readline常用的一种方法: withopen('file_name','r',encoding='utf-8')asfile:forlineinfile:print(line)##即使文件有80个G,for循环的垃圾回收体制会即时节省内存readlines()将文本文件中的每行文本作为一个字符串存入列表中,返回该列表,对于大文件会占很多内存,不建议使用 truncate() obj.truncate()#截取文件内容,根据指针位置,只保留指针之前数据注意:写文件的时候一定记着关闭文件,这里有一种自动关闭的方法: withopen("name.txt",mode="r+",encoding="utf-8")ascount:#as后面是接收打开文件对象的变量名#在缩进里写代码内容#等待运行完代码后会自动跳出缩进,就自动关闭了总结: withopen("file",'r+',encoding='utf-8')asfile_1:#打开文件时候不清空文件passimportosos.remove('file')#删除file的文件os.rename('file','file_new')#将文件名file修改为file_new文件内容的修改: 步骤: 1.先遍历文件 2.str.replace或者str.split 3.将修改后的所有文件重新写入一个新文件 4.删除原来文件 5.将新文件重命名为原来文件的名字 举例: file文件的内容: 需求1:给每一项的第一个|前的字母加上_good importos#导入os模块file_2=open("file_new",'w',encoding='utf-8')#以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容withopen("file",'r',encoding='utf-8')asfile_1:#以读模式打开file文件forlineinfile_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,其他保持不变 importos#导入os模块file_2=open("file_new",'w',encoding='utf-8')#以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容withopen("file",'r',encoding='utf-8')asfile_1:#以读模式打开file文件forlineinfile_1:list_1=line.split("|")iflist_1[0]=='zcx':#判断是不是zcxlist_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本质上是—种嵌套字典格式,但键所对应的值,往往更加复杂,不仅是数字,还可以是字符串,数组,列表等 importjsonwithopen('F:\pycharm\data\case.json',mode='r',encoding='utf-8-sig')asfile:file_case=file.read()print(type(file_case))# 1.变量指向: name="zrh"name1=nameprint(name,name1)name="zrh1"print(name,name1)#输出结果#zrhzrh#zrh1zrh内部原理: name1通过name指向zrh,此时name1的值就是zrh后面即使name改变为zrh1,name1的值也不会改变。 2.列表指向: list1=[1,2,3]list2=list1list1.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()#深拷贝importcopylist3=copy.deepcopy(list1)注意: list3最后一层是python为了节省内存才直接指向list1的数据,所以list1改变数据,是从新开辟出一块新的内存让list1指向,list3不变。 list1=[1,[2,3],4]#深拷贝importcopylist3=copy.deepcopy(list1)list1[0]=0print(list3[0])#输出结果:1