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(两边开始,中间不管,默认可移除空格、
、	)
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', '0', '0', '', '/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(列表或元祖,指定起始值)
#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
#指定	为几个字符
print('hello	world'.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'4' #bytes
num2=u'4' #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)
View Code

七、集合

#作用:去重,关系运算,

#定义:
            可变类型是不可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']))))
View Code

八、数据类型总结

按存储空间的占用分(从低到高)

数字
字符串
集合:无序,即无序存索引相关信息
元组:有序,需要存索引相关信息,不可变
列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
字典:无序,需要存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
View Code

二、打开文件的模式

文件句柄 = 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
', 'c d']

f.write('1111
222
') #针对文本模式的写,需要自己写换行符,只能是单个字符串
f.write('1111
222
'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333
','444
']) #文件模式,可以把列表写入文件
f.writelines([bytes('333
',encoding='utf-8'),'444
'.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') 
原文地址:https://www.cnblogs.com/guoyunlong666/p/8018584.html