DAY2-python数据类型、字符编码、文件处理
阅读目录
一、引子
1 什么是数据?
x=10,10是我们要存储的数据
2 为何数据要分不同的类型
数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示
3 数据类型
数字(整形,长整形,浮点型,复数)
字符串
字节串:在介绍字符编码时介绍字节bytes类型
列表
元组
字典
集合
二、数字
整数与浮点数
#整型int
作用:年纪,等级,身份证号,qq号等整型数字相关
定义:
age=10 #本质age=int(10) #浮点型float
作用:薪资,身高,体重,体质参数等浮点数相关 salary=3000.3 #本质salary=float(3000.3) #二进制,十进制,八进制,十六进制
#二:该类型总结
1 存一个值or存多个值
只能存一个值 2 无序 3 可变or不可变
!!!不可变:值变,id就变。不可变==可hash
其他数字类型(了解)
#长整形(了解)
在python2中(python3中没有长整形的概念):
>>> num=2L
>>> type(num)
<type 'long'> #复数(了解)
>>> x=1-2j
>>> x.real
1.0
>>> x.imag
-2.0
三、字符串
#作用:名字,性别,国籍,地址等描述信息 #定义:在单引号\双引号\三引号内,由一串字符组成
name='egon' #二:该类型总结
1 存一个值or存多个值
只能存一个值2 可变or不可变
!!!不可变:值变,id就变。不可变==可hash
优先掌握的操作:
#1、按索引取值(正向取+反向取) :只能取
msg='hello world'
#第一位从0开始,最后一位是-1,倒数第二位是-2。
print(msg[0],msg[-1]))
h d #2、切片(顾头不顾尾,步长)
print(msg[0:3]) #>=0 <3
hel
#不写代表从头开始,取到最后一位,如果写-1,最后一位取不到
print(msg[:])
hello world
#设定步长为2,先取第一位,隔一位取一个;默认步长是1
print(msg[0:7:2])
hlow
#反向取值,注意,顾头不顾尾,所以6能取到,而1不能
print(msg[6:1:-1])
w oll
#将字符串反转
print(msg[-1::-1])
dlrow olleh #3、长度len
print(len(msg)) #等同于,print(msg.__len__()),但是一般我们只用len()
11 #4、成员运算in和not in
print('llo' in msg)
True
print('llo' not in msg)
False #5、移除strip(两边开始,中间不管,默认可移除空格、\n、\t)
password=' alex 3714 '
print(password.strip())
alex 3714
#指定移除的字符
password='***alex3714***'
print(password.strip('*'))
alex3714
#从左边移除
password='***alex3714***'
print(password.lstrip('*'))
alex3714***
#从右边移除
print(password.rstrip('*'))
***alex3714
#与input连用
password=input('>>: ').strip() #6、切分split,默认按空格切分,切分结果存在列表中
user_info='root:x:0:0::/root:/bin/bash'
res=user_info.split(':')
print(res)
['root', 'x', '', '', '', '/root', '/bin/bash']
#指定从左向右,切割几次,默认切到结束
print(user_info.split(':',1))
['root', 'x:0:0::/root:/bin/bash']
#从右向左,切割几次,注意列表顺序还是从左向右的。
print(user_info.rsplit(':',1))
['root:x:0:0::/root', '/bin/bash'] #7、循环,把字符串每个字符遍历输出
msg='hel'
for i in msg:
print(i)
h
e
l msg='hel'
for i in range(len(msg)): #0 1 2
print(i,msg[i])
0 h
1 e
2 l
#判断一个字符串是否为空
len('') == 0
字符串类型总结
#二:该类型总结
# 1 存一个值or存多个值
# 只能存一个值 # 2 有序 # 3 可变or不可变
# !!!不可变:值变,id就变。不可变==可hash
多变量赋值
# Assign values directly
a, b = 0, 1 # Assign values from a list
r,g,b = ["Red","Green","Blue"] # Assign values from a tuple
x,y = (1,2)
#链式赋值
a=b=c=2
print(id(a),id(b),id(c))
493143760 493143760 493143760 #交叉赋值
m=1
n=2
m,n=n,m
print(m,n) #解压
l=[1,2,3,4]
a,b,c,d=l
print(a,b,c,d)
1 2 3 4 #用_作为占位符
l=[1,2,3,4]
a,_,_,d=l
print(a,d) #可以使用*_表示多个
a,*_,d=l
print(a,d)
各种赋值
range
#renge(起始值,结束值,步长)
#用于获取指定范围内的数。
#在2.7中,使用range会创建所有数字,占用内存。xrange是默认不创建,只在for循环中,一个循环创建一个;3中range就等同于xrange,xrange也移除了。
#默认从0开始,顾头不顾尾
for i in range(3):
print(i)
0
1
2
#指定开始值开始
for i in range(1,3,1):
print(i)
1
2
#反向取值
for i in range(3,1,-1)
print(i)
3
2
#enumerate(列表或元祖,指定起始值)
#enumerate自动生成一列从0开始自增1的数字,通过for循环与列表或者元祖的每个元素组成新的元祖。 li = ['电脑','鼠标','游艇','U盘']
for key in enumerate(li):
print(key)
(0, '电脑')
(1, '鼠标')
(2, '游艇')
(3, 'U盘') #enumerate(li,1)生成从1开始自增1的数,注意虽然1对应电脑,但是取值的索引还是0。
li = ('电脑','鼠标','游艇','U盘')
for x,y in enumerate(li,1):
print(x,y)
1 电脑
2 鼠标
3 游艇
4 U盘
需要掌握的操作
#1、partition,rpartition
#指定分割符,将字符串分割成三部分,保存到元祖中,只分割一次
msg='hello word'
print(msg.partition('o'))
('hell', 'o', ' word')
#从又向左找分隔符
msg='hello word'
print(msg.rpartition('o'))
('hello w', 'o', 'rd') #2、lower,upper
#将字符串大写
print('ALeX'.lower())
#将字符串小写
print('aaa'.upper()) #3、startswith,endswith
#0开始5结束是否以'a'开始
msg='alex is SB'
print(msg.startswith('a',0,5))
True
#字符串是否以B结尾
print(msg.endswith('B')) #4、join
#将元素都是字符串的列表或元祖的每个元素以指定字符串拼接(注意这是字符串的功能)
li=['aa','bb','cc']
print('_'.join(li))
aa_bb_cc
#如果元素中有数字,就会报错 #5、replace
#将前面的内容替换成后面的内容,指定替换几次,默认全部替换
msg='alex say my name is alex ,alex have on tesla'
print(msg.replace('alex','SB',1))
SB say my name is alex ,alex have on tesla #6、isdigit
#isdigit:可以判断bytes和unicode类型,是最常用的用于于判断字符是否为"数字"的方法
age=input('>>: ')
print(age.isdigit())
其他操作(了解即可)
#1、find,rfind,index,rindex,count
#find找到字符串所在索引,不存在返回-1
msg='hello world'
print(msg.find('wo'))
#rfind反方向开始找
#index,rindex找索引,不存在报错
print(msg.index('SB')) #ValueError: substring not found
#count,统计有多少个。
print(msg.count('l'))
print(msg.count('l',0,5)) #指定范围 #2、center,ljust,rjust,zfill
#center,居中,其余地方默认用空格填充
print('egon'.center(30,'*'))
#ljust,左对齐
print('egon'.ljust(30,'*'))
#rjust,右对齐
print('egon'.rjust(30,'*'))
#zfill,居右,用0填充
00000000000000000000000000egon #3、expandtabs
#指定\t为几个字符
print('hello\tworld'.expandtabs(10))
hello world #4、captalize,swapcase,title
#captalize、将字符串首字母大写
print('i am egon'.capitalize())
I am egon
#swapcase、大小写反转
print('AbC'.swapcase())
#title、将每个单词首字母大写
print('i am egon'.title()) #5、is数字系列(不能判断浮点数)
num1=b'' #bytes
num2=u'' #unicode,python3中无需加u就是unicode
num3='壹' #中文数字
num4='Ⅳ' #罗马数字
isdigit()能识别:bytes,unicode的数字
isdecimal()能识别:unicode的数字
isnumeric()能识别:unicode,中文,罗马的数字 #6、is其他
# name='egon123'
# print(name.isalnum()) #字符串由字母或数字组成
# print(name.isalpha()) #字符串只由字母组成
# print('abcA'.islower())#判断都是小写
# print(name.isupper())#判断都是大写
# print(' '.isspace())#判断是不是空格(不是空)
# print('Am Ia'.istitle())#判断是不是标题
#判断字符串是否是合法的标识符,字符串仅包含中文字符合法
print('print1111'.isidentifier())
#实际上这#里判断的是变量名是否合法。如:
'_a'.isidentifier() -->True
'3a'.isidentifier() -->False
'中国'.isidentifier() -->True
注意:所有修改字符串的操作都是新生成一个字符串,而不是修复源字符串,因为字符串是不可变的。
四、列表
#作用:多个装备,多个爱好,多门课程,多个女朋友等 #定义:[]内可以有多个任意类型的值,逗号分隔
my_girl_friends=['alex','wupeiqi','yuanhao',4,5] #本质my_girl_friends=list([...])
或
l=list('abc')
优先掌握的操作:
1、按索引存取值(正向存取+反向存取):即可存也可以取
#取值与字符串操作一样
#对其中元素从新赋值,就是改变原列表
my_girl_friends=['alex','wupeiqi','yuanhao',4,5]
print(my_girl_friends[1])
my_girl_friends[1]='bbb'
print(my_girl_friends) wupeiqi
['alex', 'bbb', 'yuanhao', 4, 5]
2、切片(顾头不顾尾,步长)
#与列表操作一致
#ps:反向步长
l=[1,2,3,4,5,6] #正向步长
l[0:3:1] #[1, 2, 3]
#反向步长
l[2::-1] #[3, 2, 1]
#列表翻转
l[::-1] #[6, 5, 4, 3, 2, 1]
3、长度len(元素个数)
#实际上也是在调用__len__()
print(my_girl_friends.__len__())
print(len(my_girl_friends))
4、成员运算in和not in
print('wupeiqi' in my_girl_friends)
True
5、追加append
#列表不能通过定义新索引来追加,会报错
my_girl_friends=['alex','wupeiqi','yuanhao',4,5]
my_girl_friends[5]=3 #IndexError: list assignment index out of range
my_girl_friends.append(6)
print(my_girl_friends)
['alex', 'wupeiqi', 'yuanhao', 4, 5, 6]
6、删除del、remove、pop
my_girl_friends=['alex','wupeiqi','yuanhao',4,5]
#1、单纯的删除、不能把删除的值赋给其他变量
del my_girl_friends[0]
print(my_girl_friends)
['wupeiqi', 'yuanhao', 4, 5] res=my_girl_friends.remove('yuanhao')
print(my_girl_friends)
print(res)
['alex', 'wupeiqi', 4, 5]
None #2、删除并拿到结果:取走一个值,指定索引,不指定从最后一个开始
res=my_girl_friends.pop(2)
print(my_girl_friends)
print(res)
['alex', 'wupeiqi', 4, 5]
yuanhao my_girl_friends=['alex','wupeiqi','yuanhao',4,5]
print(my_girl_friends.pop(0)) #'alex'
print(my_girl_friends.pop(0)) #'wupeqi'
print(my_girl_friends.pop(0)) #'yuanhao'
7、循环
#每次循环得到一个元素
my_girl_friends=['alex','wupeiqi','yuanhao',4,5]
for i in my_girl_friends:
print(i)
要掌握的方法:
1、插入insert
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
my_girl_friends.insert(1,'egon')
print(my_girl_friends)
['alex', 'egon', 'wupeiqi', 'yuanhao', 'yuanhao', 4, 5]
2、清除clear
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
my_girl_friends.clear()
print(my_girl_friends)
[]
3、统计count
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
print(my_girl_friends.count('yuanhao'))
2
4、拷贝copy
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
l=my_girl_friends.copy()
print(l)
['alex', 'wupeiqi', 'yuanhao', 'yuanhao', 4, 5]
5、扩展extend
#append和insert都只能加入一个值,extend的可以添加多个
#字符串、列表,元祖,字典等可for循环的,都可以被extend
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
l=['egon1','egon2']
my_girl_friends.extend(l)
my_girl_friends.extend('hello')
6、取索引index
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
print(my_girl_friends.index('wupeiqi'))
print(my_girl_friends.index('wupeiqissssss'))
#不存在报错ValueError: 'wupeiqissssss' is not in list
7、反转列表reverse
my_girl_friends=['alex','wupeiqi','yuanhao','yuanhao',4,5]
my_girl_friends.reverse()
print(my_girl_friends)
[5, 4, 'yuanhao', 'yuanhao', 'wupeiqi', 'alex']
8、列表排序sort
#正向排序
l=[1,10,4,11,2]
l.sort()
print(l)
[1, 2, 4, 10, 11] #反向排序
l.sort(reverse=True)
print(l)
[11, 10, 4, 2, 1] #注意:
#字符串排序是从左向右一个一个比对,按照ascii的顺序比对
#列表只能是纯数字或者纯字符串才能排序,否则报错
#二:该类型总结
# 1 存一个值or存多个值
# 可以存多个值,值都可以是任意类型 # 2 有序 # 3 可变or不可变
# !!!可变:值变,id不变。可变==不可hash
注意:所有修改列表的操作都是直接操作源列表的。
五、元祖
#作用:存多个值,对比列表来说,元组不可变(是可以当做字典的key的),主要是用来读,如果元祖元素是列表或者字典,则列表或字典的元素是可以变的。 #定义:与列表类型比,只不过[]换成()
age=(11,22,33,44,55)本质age=tuple((11,22,33,44,55)) #优先掌握的操作:
#1、按索引取值(正向取+反向取):只能取
#2、切片(顾头不顾尾,步长)
#3、长度
#4、成员运算in和not in
#5、循环
#与列表都一样
需要掌握的内容
#1、查找索引 index
age=(11,22,33,44,55)
print(age.index(33))
print(age.index(33333)) #不存在报错 #2、统计count
print(age.count(33))
#二:该类型总结
# 1 存一个值or存多个值
# 可以存多个值,值都可以是任意类型 # 2 有序 # 3 可变or不可变
# !!!不可变:值变,id就变。不可变==可hash
六、字典
#作用:存多个值,key-value存取,取值速度快 #定义:key必须是不可变类型,value可以是任意类型
info={'name':'egon','age':18,'sex':'male'} #本质info=dict({....})
或
info=dict(name='egon',age=18,sex='male')
或
info=dict([['name','egon'],('age',18)])
或
{}.fromkeys(('name','age','sex'),None) #除了元祖还可以是列表,字符串等可迭代的数据,然后每个键都赋值为None,可以批量创建键值对
#fromkeys()的定义:
def fromkeys(*args, **kwargs): # 将所有key都赋予相同的值,第一参数为key,第二个参数为value,如果没有第二个参数则默认为none;
#注意!!!是将所有key都赋予同一个值,比如如果value是一个[],则所有value指向的内存地址是同一个地址,也就是说往一个key的[]中append一个数据,则所有key的[]都被append了一个同样的数据,因为所有[]是同一个内存地址。 #如果想让value不一样, 可以这样:
test = {}
for i in range(10):
test[i] = []
fromkeys()的坑
优先掌握的内容
#1、按key存取值:可存可取
可通过赋值一个不存在的key,来增加新的键值对。
d={'name':'egon'}
print(d['name'])
d['age']=18
print(d) #2、长度len,键值对个数
info={'name':'egon','age':18,'sex':'male'}
print(len(info))
3 #3、成员运算in和not in,针对key的,而不是值value
info={'name':'egon','age':18,'sex':'male'}
print('name' in info)
True
print('egon' in info)
False #4、删除
#pop,移除指定键值对,并得到value
info={'name':'egon','age':18,'sex':'male'}
print(info.pop('name'))
print(info)
egon
{'age': 18, 'sex': 'male'}
#key不存在会报错,可指定不存在的key返回值而不报错。
print(info.pop('name111',None))
None #popitem,删除最后一个键值对(尽量当做无序的),得到键值对
info={'name':'egon','age':18,'sex':'male'}
print(info.popitem())
('sex', 'male') #5、键keys(),值values(),键值对items() #了解
print(info.keys()) #打印所有键
print(list(info.keys())[0]) #转换成列表取元素
print(list(info.values())) #打印所有值
print(list(info.items())) #打印所有键值对 #6、循环
#默认是对key进行循环
info={'name':'egon','age':18,'sex':'male'}
for k in info:
print(k,info[k])
for v in info.values():
print(v)
需要掌握的内容
#1、取值get
info={'name':'egon','age':18,'sex':'male'}
print(info['hobbies']) #取不存在的key报错退出
print(info.get('hobbies')) #使用get不会报错
None
print(info.get('hobbies','没有')) #指定返回值 #2、update 、把一个字典加入另一个字典
info={'name':'egon','age':18,'sex':'male'}
d={'x':1,'y':2,'name':'EGON'}
info.update(d)
print(info)
{'name': 'EGON', 'age': 18, 'sex': 'male', 'x': 1, 'y': 2} #3、setdefault,如果key存在,则不修改,返回已经有的key对应的value
info={'name':'egon','age':16,'sex':'male'}
value=info.setdefault('age',18)
print(value)
print(info)
16
{'name': 'egon', 'age': 16, 'sex': 'male'}
#如果key不存在,则新加一个键值对
info={'name':'egon','age':16,'sex':'male'}
hobbies_list=info.setdefault('hobbies',[])
print(hobbies_list)
hobbies_list.append('play')
hobbies_list.append('read')
print(info)
[]
{'name': 'egon', 'age': 16, 'sex': 'male', 'hobbies': ['play', 'read']}
#二:该类型总结
# 1 存一个值or存多个值
# 可以存多个值,值都可以是任意类型,key必须是不可变类型
#
# 2 无序 # 3 可变or不可变
# !!!可变:值变,id不变。可变==不可hash
练习:
统计s='hello alex alex say hello sb sb'中每个单词的个数 结果如:{'hello': 2, 'alex': 2, 'say': 1, 'sb': 2}
#利用setdefault解决重复赋值
'''
setdefault的功能
1:key存在,则不赋值,key不存在则设置默认值
2:key存在,返回的是key对应的已有的值,key不存在,返回的则是要设置的默认值
d={}
print(d.setdefault('a',1)) #返回1 d={'a':2222}
print(d.setdefault('a',1)) #返回2222
'''
s='hello alex alex say hello sb sb'
dic={}
words=s.split()
for word in words: #word='alex'
dic.setdefault(word,s.count(word))
print(dic)
七、集合
#作用:去重,关系运算, #定义:
可变类型是不可hash类型 #定义集合:
集合:可以包含多个元素,用逗号分割,
集合的元素遵循三个原则:
1:每个元素必须是不可变类型(可hash,可作为字典的key)
2:没有重复的元素
3:无序 注意集合的目的是将不同的值存放到一起,不同的集合间用来做关系运算,无需纠结于集合中单个值
优先掌握内容
#优先掌握的操作:
#1、定义集合:{}内用逗号分割每个元素都必须是不可变类型,元素不能重复,无序
s={1,2,3,1} #s=set({1,2,3,1}) #1、长度len
print(len(s)) #2、成员运算in和not in
names={'egon','alex'}
print('egon' in names)
pythons={'egon','axx','ysb','wxx'}
linuxs={'egon','oldboy','oldgirl','smallboy','smallgirl'} #3、|合集:老男孩所有的学生
print(pythons | linuxs)
print(pythons.union(linuxs)) #4、&交集:同时报名两门课程的学生
print(pythons & linuxs)
print(pythons.intersection(linuxs)) #5.1、-差集:只报名python课程的学生
print(pythons - linuxs)
print(pythons.difference(linuxs)) #5.2、-差集:只报名linux课程的学生
print(linuxs-pythons)
print(linuxs.difference(pythons)) #6、^对称差集:没有同时报名两门课程
print(pythons ^ linuxs)
print(pythons.symmetric_difference(linuxs))
#7、==
s1={1,2}
s2={1,2}
print(s1 == s2)
True
#8、父集:>,>=
print(s1 >= s2)
print(s1.issuperset(s2)) #9、子集:<,<=
print(s2 <= s1)
print(s2.issubset(s1))
#10、循环
linuxs={'egon','oldboy','oldgirl','smallboy','smallgirl'}
for student in linuxs:
print(student)
了解的知识点
#1、pop随机取走
s2={1,2,3,4,5,'a'}
print(s2.pop())
print(s2)
1
{2, 3, 4, 5, 'a'} #2、add添加
s2={1,2,3,4,5,'a'}
s2.add('b')
print(s2)
{1, 2, 3, 4, 5, 'a', 'b'} #3、删除
#discard删除不存在的元素不报错
s2={1,2,3,4,5,'a'}
s2.discard('b') #remove删除不存在的元素报错
s2={1,2,3,4,5,'a'}
s2.remove('b') #4、isdisjoint两个集合没有共同部分时,返回值为True
s1={1,2,3,4,5,'a'}
s2={'b','c',}
print(s1.isdisjoint(s2))
True #5、把可迭代的数据转换成集合
# l=['a','b',1,'a','a']
# print(list(set(l)))
# print(set('hello'))
# print(set({'a':1,'b':2,'c':3})) #6、把差集从新赋值给集合
s1={1,2,3}
s2={1,2,}
print(s1-s2)
print(s1.difference(s2))
s1.difference_update(s2) #s1=s1.difference(s2)
print(s1)
{3}
{3}
{3}
二.去重 1. 有列表l=['a','b',1,'a','a'],列表元素均为可hash类型,去重,得到新列表,且新列表无需保持列表原来的顺序 2.在上题的基础上,保存列表原来的顺序 3.去除文件中重复的行,肯定要保持文件内容的顺序不变
4.有如下列表,列表元素为不可hash类型,去重,得到新列表,且新列表一定要保持列表原来的顺序 l=[
{'name':'egon','age':18,'sex':'male'},
{'name':'alex','age':73,'sex':'male'},
{'name':'egon','age':20,'sex':'female'},
{'name':'egon','age':18,'sex':'male'},
{'name':'egon','age':18,'sex':'male'},
]
#去重,无需保持原来的顺序
l=['a','b',1,'a','a']
print(set(l)) #去重,并保持原来的顺序
#方法一:不用集合
l=[1,'a','b',1,'a'] l1=[]
for i in l:
if i not in l1:
l1.append(i)
print(l1)
#方法二:借助集合
l1=[]
s=set()
for i in l:
if i not in s:
s.add(i)
l1.append(i) print(l1) #同上方法二,去除文件中重复的行
import os
with open('db.txt','r',encoding='utf-8') as read_f,\
open('.db.txt.swap','w',encoding='utf-8') as write_f:
s=set()
for line in read_f:
if line not in s:
s.add(line)
write_f.write(line)
os.remove('db.txt')
os.rename('.db.txt.swap','db.txt') #列表中元素为可变类型时,去重,并且保持原来顺序
l=[
{'name':'egon','age':18,'sex':'male'},
{'name':'alex','age':73,'sex':'male'},
{'name':'egon','age':20,'sex':'female'},
{'name':'egon','age':18,'sex':'male'},
{'name':'egon','age':18,'sex':'male'},
]
# print(set(l)) #报错:unhashable type: 'dict'
s=set()
l1=[]
for item in l:
val=(item['name'],item['age'],item['sex'])
if val not in s:
s.add(val)
l1.append(item) print(l1) #定义函数,既可以针对可以hash类型又可以针对不可hash类型
def func(items,key=None):
s=set()
for item in items:
val=item if key is None else key(item)
if val not in s:
s.add(val)
yield item print(list(func(l,key=lambda dic:(dic['name'],dic['age'],dic['sex']))))
八、数据类型总结
按存储空间的占用分(从低到高)
数字
字符串
集合:无序,即无序存索引相关信息
元组:有序,需要存索引相关信息,不可变
列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
字典:无序,需要存key与value映射的相关信息,可变,需要处理数据的增删改
按存值个数区分
标量/原子类型 | 数字,字符串 |
容器类型 | 列表,元组,字典 |
按可变不可变区分
可变 | 列表,字典 |
不可变 | 数字,字符串,元组 |
按访问顺序区分
直接访问 | 数字 |
顺序访问(序列类型) | 字符串,列表,元组 |
key值访问(映射类型) | 字典 |
九、运算符
详细:http://www.cnblogs.com/linhaifeng/articles/5935801.html#_label34
十、字符编码
1、存取文件不乱码的法则:用什么编码存的,就要用什么编码读
2、
unicode-----encode----->gbk (编码)
gbk-------->decode----->unicode (解码) 3、
python3解释器默认使用的字符编码是utf-8
python2解释器默认使用的字符编码是ascii
内存中使用的是unicode
4
python2的str就是python3的bytes
python2的unicode就是python3的str
详细:http://www.cnblogs.com/linhaifeng/articles/5950339.html
十一、文件处理
一、文件操作
1、操作文件的流程
#1. 打开文件,得到文件句柄并赋值给一个变量
f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r #2. 通过句柄对文件进行操作
data=f.read() #3. 关闭文件
f.close()
2、 f=open('a.txt','r')的过程分析
#1、由应用程序向操作系统发起系统调用open(...) #2、操作系统打开该文件,并返回一个文件句柄给应用程序 #3、应用程序将文件句柄赋值给变量f
注意!!!:
#强调第一点:
打开一个文件包含两部分资源:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
1、f.close() #回收操作系统级打开的文件
2、del f #回收应用程序级的变量 其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,
而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close() 我们推荐傻瓜式操作方式:使用with关键字来帮我们管理上下文,不需要自己调用close
with open('a.txt','w') as f:
pass with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
data=read_f.read()
write_f.write(data)
1、关闭文件
#强调第二点:
f=open(...)是由操作系统打开文件,那么如果我们没有为open指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。
这就用到了上节课讲的字符编码的知识:若要保证不乱码,文件以什么方式存的,就要以什么方式打开。 f=open('a.txt','r',encoding='utf-8')
2、字符编码
3、python2中的file与open
#首先在python3中操作文件只有一种选择,那就是open() #而在python2中则有两种方式:file()与open()
两者都能够打开文件,对文件进行操作,也具有相似的用法和参数,但是,这两种文件打开方式有本质的区别,file为文件类,用file()来打开文件,相当于这是在构造文件类,而用open()打开文件,是用python的内建函数来操作,我们一般使用open()打开文件进行操作,而用file当做一个类型,比如type(f) is file
二、打开文件的模式
文件句柄 = open('文件路径', '模式')
模式可以是以下方式以及他们之间的组合:
Character | Meaning |
‘r' | open for reading (default) |
‘w' | open for writing, truncating the file first |
‘a' | open for writing, appending to the end of the file if it exists |
‘b' | binary mode |
‘t' | text mode (default) |
‘+' | open a disk file for updating (reading and writing) |
‘U' | universal newline mode (for backwards compatibility; should not be used in new code) |
#1. 打开文件的模式有(默认为文本模式):
r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 之追加写模式【不可读;不存在则创建;存在则只追加内容;注意:a模式打开文件首先把光标移动到最后】 #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 #3. 了解部分
"+" 表示可以同时读写某个文件
r+, 读写【可读,可写】
w+,写读【可读,可写】
a+, 写读【可读,可写】 x, 只写模式【不可读;不存在则创建,存在则报错】
x+ ,写读【可读,可写】
xb
三、操作文件的方法
a b
c d
#掌握
f.read() #读取所有内容,存放到字符串中,光标移动到文件末尾
a b
c d
f.readline() #读取一行内容,存放到字符串在,光标移动到第二行首部
a b
f.readlines() #读取每一行内容,存放于列表中,注意有换行符
['a b\n', 'c d'] f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符,只能是单个字符串
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式,可以把列表写入文件
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式 #了解
f.readable() #文件是否可读
f.writable() #文件是否可读
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
f.name
四、文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符(只有这种模式时光标是以字符移动的)
with open('c.txt','rt',encoding='utf-8') as f:
print(f.read(6))
print(f.tell())
2. 文件打开方式为b模式时,代表读取3个字节
with open('c.txt','rb') as f:
print(f.read(6))
f.seek(2,1)
print(f.tell())
print(f.read().decode('utf-8'))
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
注意:
1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
0模式:以文件最开始为参照,f.seek(6,0) 将光标从文件最开始向后移动6个字节
1模式:以当前位置为参照,f.seek(6,1) 将光标从当前位置向后移动6个字节;f.seek(-6,1)将光标从当前位置向前移动6个字节
2模式:以文件最末为参照,f.seek(0,2)将光标移动到文件最后;f.seek(-6,2)将光标从最后向前移动6个字节
2.tell获取当前文件读取指针的位置:print(f.tell())
3. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
如果指定了可选参数 size,则表示截断文件为 size 个字节。 如果没有指定 size,则从当前位置起截断;截断之后 size 后面的所有字符被删除。
with open('access.log','a',encoding='utf-8') as f:
f.truncate(3)
import time
with open('test.txt','rb') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
print(line.decode('utf-8'))
else:
time.sleep(0.2)
练习:基于seek实现tail -f功能
五、文件的修改
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)
import os with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
data=read_f.read() #全部读入内存,如果文件很大,会很卡
data=data.replace('alex','SB') #在内存中完成修改 write_f.write(data) #一次性写入新文件 os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
import os with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
for line in read_f:
line=line.replace('alex','SB')
write_f.write(line) os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
DAY2-python数据类型、字符编码、文件处理的更多相关文章
- python第二周数据类型 字符编码 文件处理
第一数据类型需要学习的几个点: 用途 定义方式 常用操作和内置的方法 该类型总结: 可以存一个值或者多个值 只能存储一个值 可以存储多个值,值都可以是什么类型 有序或者无序 可变或者不可变 二:数字整 ...
- Python常见字符编码间的转换
主要内容: 1.Unicode 和 UTF-8的爱恨纠葛 2.字符在硬盘上的存储 3.编码的转换 4.验证编码是否转换正确 5.Python bytes类型 前 ...
- Python基础-字符编码与转码
***了解计算机的底层原理*** Python全栈开发之Python基础-字符编码与转码 需知: 1.在python2默认编码是ASCII, python3里默认是utf-8 2.unicode 分为 ...
- Python的字符编码
Python的字符编码 1. Python字符编码简介 1. 1 ASCII Python解释器在加载.py文件的代码时,会对内容进行编码,一般默认为ASCII码.ASCII(American St ...
- python 3字符编码
python 3字符编码 官方链接:http://legacy.python.org/dev/peps/pep-0263/ 在Python2中默认是ascii编码,Python3是utf-8编码 在p ...
- Python 的字符编码
配置: Python 2.7 + Sublime Text 2 + OS X 10.10 本文意在理清各种编码的关系并以此解决 Python 中的编码问题. 1 编码基本概念 只有先了解字符表.编码字 ...
- 转:Python常见字符编码及其之间的转换
参考:Python常见字符编码 + Python常见字符编码间的转换 一.Python常见字符编码 字符编码的常用种类介绍 第一种:ASCII码 ASCII(American Standard Cod ...
- Python常用字符编码(转)
Python常用字符编码 字符编码的常用种类介绍 第一种:ASCII码 ASCII(American Standard Code for Information Interchange,美国信息交 ...
- Python之字符编码与文件操作
目录 字符编码 Python2和Python3中字符串类型的差别 文件操作 文件操作的方式 文件内光标的移动 文件修改 字符编码 什么是字符编码? ''' 字符编码就是制定的一个将人类的语言的字符与二 ...
- what's the python之字符编码与文件处理
用文本编辑器打开一个文件就是把一个文件读入了内存中 ,所以打开文件的操作也是在内存中的,断电即消失,所以若要保存其内容就必须点击保存让其存入硬盘中 python解释器执行py文件的原理 : 第一阶段: ...
随机推荐
- svg_鼠标手型
1. 貌似是 属性 "cursor :pointer;",待测试. 2.
- MVP实战心得—封装Retrofit2.0+RxAndroid+RxBus
响应式编程框架,rxjava的扩展,很爽的链式编程 魅力在于对数据的处理,与线程切换的灵活性. 用来处理异步操作(Lambda表达式不会用.用Lambda表达式代码会更少,但不会的人会看不懂代码.不是 ...
- review17
关于构造方法Random(long seed)的理解 无参构造方法使用的默认参数是系统当前的毫秒数.使用同一数值的种子参数,生成的随机数也是一样的. 代码如下所示: import java.util. ...
- Mac上的抓包工具Charles[转载]
今天就来看一下Mac上如何进行抓包,之前有一篇文章介绍了使用Fidder进行抓包 http://blog.csdn.net/jiangwei0910410003/article/details/198 ...
- ADO.NET实体框架Entity Framework模型-基于元数据解析
上一篇简单介绍了EF的XML模型结构,在基于xml解析一文中,主要使用xml查询技术Xpath,XQuery来得到实体模型中相应信息的,由于这种方式在数据库庞大,表关系复杂的情况下,有诸 ...
- String随笔
1.古罗马皇帝凯撒在打仗时曾经使用过以下方法加密军事情报:,请编写一个程序,使用上述算法加密或解密用户输入的英文字串要求设计思想.程序流程图.源代码.结果截图. 设计思想:1)定义一个String类型 ...
- idea更换git地址操作
更换地址: git remote set-url origin XXXXXXXXXXXXXXX 查看远程地址: git remote -v
- Maven下载 || 配置本地仓库 || IntelliJ IDEA配置Maven教程
本文章主要介绍1.Maven下载 2.配置本地仓库Repository 3.IDEA配置Maven 三点. 相关博客: Eclipse配置Maven https://www.cnblogs.c ...
- nyoj-1011-So Easy[II] (多边形面积求解)
题目链接 /* Name:nyoj-1011-So Easy[II] Copyright: Author: Date: 2018/4/26 17:12:09 Description: 将多边形,从第一 ...
- Mat ,IplImage, CvMat 之间的转换的总结
在新版本与旧版本之间纠结,到底是用Mat,还是Iplimage? Mat 侧重于数据计算,而Iplimage注重于图像的处理. 因此,应根据具体需要灵活使用,那个好用用哪个,只要在两者之间进行转换即可 ...