字符编码
字符编码部分内容取自:http://www.cnblogs.com/linhaifeng/articles/5950339.html
1.文本编辑器存取文件的原理(nodepad++,pycharm,word)
打开编辑器就打开了启动了一个进程,是在内存中的,所以在编辑器编写的内容也都是存放与内存中的,断电后数据丢失
因而需要保存到硬盘上,点击保存按钮,就从内存中把数据刷到了硬盘上。在这一点上,我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。
2. python解释器执行py文件的原理
例如python test.py
第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器
第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中
第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码
总结:
python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样
与文本编辑器不一样的地方在于,python解释器不仅可以读文件内容,还可以执行文件内容
计算机要想工作必须通电,也就是说‘电’驱使计算机干活,而‘电’的特性,就是高低电平(高低平即二进制数1,低电平即二进制数0),也就是说计算机只认识数字
3.字符编码
编程的目的是让计算机干活,而编程的结果说白了只是一堆字符,也就是说我们编程最终要实现的是:一堆字符驱动计算机干活
所以必须经过一个过程:
字符--------(翻译过程)------->数字
这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码
总结:
无论是何种编辑器,要防止文件出现乱码(请一定注意,存放一段代码的文件也仅仅只是一个普通文件而已,此处指的是文件没有执行前,我们打开文件时出现的乱码)
核心法则就是,文件以什么编码保存的,就以什么编码方式打开
文件操作
- Open()默认encoding是gbk,是Windows的默认编码
f = open('员工信息表','r')
date = f.read()
print(date)
这样执行会报错:
date = f.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 67: illegal multibyte sequence
原因就是存的时候文件以utf-8的编码保存,但是读的时候open在Windows上默认是gbk的方式读,读和写的编码不一样所以报错。
解决方法就是后面加上encoding=‘utf-8’
- Cpu有两种状态,内核态和用户态,内核态是操作系统对计算机硬件有完全的操作权限,用户态是用户在使用,但是用户态没有对计算机硬件操作的权限需要通过操作系统进行调用。
- Open操作打开文件时光标停留在文件开始,但是执行完read操作以后,光标移动到了最后,所以在读取的时候读不到东西了
f = open('员工信息表','r',encoding='utf-8')
date = f.read()
print(date)
date2=f.read()
print('==========>',date2)
输出结果:
1,AlexLi,22,13600000000,IT,2013-04-01
2,wangyang,30,13700000000,销售,2014-04-01
3,eric,42,13800000000,厨师,2014-11-01
4,dodo,18,13900000000,老板,2013-09-09
==========>
- 操作光标seek()
f.seek(0)光标移动到开始,详细讲解见19
Buffer和catch
数据从内存写到硬盘,肯定存在速度差,所以数据量小的时候先存储到buffer,然后统一写入硬盘,减少速度差
读到内存中数据时,Catch是cpu经常用到的数据存储到catch中
判断文件是否是关闭状态print(f.closed())
查看文件编码print(f.encoding())
查看文件名print(f.name())
查看文件是否是可读状态print(f.readable())即是否是r打开的
一行一行的读readline()
f = open('员工信息表','r',encoding='utf-8')
print(f.readline())
print('========')
运行结果:
1,AlexLi,22,13600000000,IT,2013-04-01
========
可以看到有一个空行,为什么呢,因为虽然看到文件是一行行的,其实只是一个字符串,看到的换行其实是‘ ’的效果(windows是 ),加上print默认末尾是换行,所以看到了一个空行
print(f.readline(),end='')这样打印就不会有空行了
Readlines()
以列表形式存取所有行
f = open('员工信息表','r',encoding='utf-8')
print(f.readlines())
执行结果:
['1,AlexLi,22,13600000000,IT,2013-04-01 ','2,wangyang,30,1370000000,销售,2014-04-01 ', '3,eric,42,13800000000,厨师,2014-11-01 ', '4,dodo,18,13900000000,老板,2013-09-09']
Open的参数
""" Character Meaning
--------- ---------------------------------------------------------------
'r' open for reading (default)
'w' open for writing, truncating the file first打开文件会清空文件内容,有则清空,没有创建
'x' create a new file and open it for writing
'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 (deprecated)通用换行模式,该模式会吧所有换行符( , , )都替换为 ,不加‘rU’不会因为系统不同而换行不同"""
‘w’以写的方式打开
f.write(‘1111 2222’)
f.writelines()里面写列表或者元组
‘+’和with
With open(‘文件名’,‘模式’)
模式有‘r+’读写,没有文件报错
‘W+’写读,没有文件新建
‘a+’追加读,没有不报错,新建该文件
For…else while…wlse
在for和while循环中,正常循环结束会执行else,如果被break打断则不会执行else
Rb模式可以读取图片什么的
f.read(字符数)
源文件内容:你好www哦
f = open('员工信息表啊','r')#,encoding='utf-8'
date=f.read(3)
print(date)
输出结果:
你好w
Ps:中文英文都是一个字符,源文件编码为gbk所以这里去掉了encoding
f = open('员工信息表啊','rb')#,encoding='utf-8'
date=f.read(4)
print(date.decode('gbk'))
成功输出两个gbk编码格式的字符
date=f.read(3)
print(date.decode('gbk'))
因为gbk格式两个byte为一个字,所以这里报错
UnicodeDecodeError: 'gbk' codec can't decode byte 0xc5 in position 2: incomplete multibyte sequence
seek()光标移动字节
f = open('员工信息表啊','rb')#,encoding='utf-8'
f.seek(2)
date=f.read(3)
print(date.decode('gbk'))
date=f.read(1)
print(date.decode('gbk'))
ps:seek移动的是byte字节!
Seek(n,m)
N为移动几个字节,
M表示的是从什么位置开始,0为开始,1为现在的位置(相对位置),2为文件末尾
Ps:只能在‘rb’模式下使用
f.tell()返回当前光标所在位置
f.truncate()截断--字节截断
源文件:你好啊,www
f = open('员工信息表啊','r+',encoding='utf-8')
f.truncate(10)
在utf-8的编码下,中文占三个字节,‘,’为英文的逗号,占一个字节,如果是中文格式下的逗号占三个字节,如果在中间被截断,则出现乱码,截断后改变的是文件本身
文件变成:你好啊,
函数
先定义再使用
从宏观角度分为形参和实参
形参:#定义阶段
# def foo(x,y): #x=1,y=2
# print(x)
# print(y)
实参:调用阶段
# foo(1,2)
详细的函数参数分为五种
位置参数
#位置参数
# def foo(x,y,z):#位置形参:必须被传值的参数
# print(x,y,z)
#
# # foo(1,2,3)
# foo(1,2,3) #位置实参数:与形参一一对应
关键字参数
def foo(x,y,z):
print(x,y,z)
# foo(z=3,x=1,y=2)
在传值的时候对应形参的名字
关键字参数需要注意的问题:
# 1:关键字实参必须在位置实参后面
# 2: 不能重复对一个形参数传值
# foo(1,z=3,y=2) #正确
# foo(x=1,2,z=3) #错误
# foo(1,x=1,y=2,z=3)
def ree(x,y,z):
print(x,y,z)
ree(11,12,x=6)
错误!TypeError: ree() got multiple values for argument 'x'
默认参数
默认参数
# def register(name,age,sex='male'): #形参:默认参数
# print(name,age,sex)
#
# register('asb',age=40)
# register('a1sb',39)
# register('a2sb',30)
# register('a3sb',29)
#
# register('钢蛋',20,'female')
# register('钢蛋',sex='female',age=19)
注意
#默认参数需要注意的问题:
#一:默认参数必须跟在非默认参数后
# def register(sex='male',name,age): #在定义阶段就会报错
# print(name,age,sex)
#(了解)二:默认参数在定义阶段就已经赋值了,而且只在定义阶段赋值一次
# a=100000000
# def foo(x,y=a):
# print(x,y)
# a=0
# foo(1)
#三:默认参数的值通常定义成不可变类型
可变长参数(*args,**kwargs)
*args元组类型
Ps:*会把溢出的按位置定义的实参都接收,以元组的形式赋值给args
def ree(x,y,*args):
print(x,y,*args)
ree(11,12,66,77,88)
输出结果:11 12 66 77 88
def ree(x,y,*args):
print(args)
ree(11,12,66,77,88)
输出结果:(66, 77, 88)
**kwargs字典类型
Ps: **会把溢出的按关键字定义的实参都接收,以字典的形式赋值给kwargs
def ree(x,y,**kargs):
print(kargs)
ree(11,12,d=66,a=77,b=88)
输出结果:
{'b': 88, 'a': 77, 'd': 66}
def ree(x,y,m='aaaa',**kargs):
print(kargs)
ree(11,12,66,a=77,b=88)
这样m的默认值变为了66,所以这样不传变量名是可以的
混合
def wrapper(*args,**kwargs):
print(args)
print(kwargs)
wrapper(1,2,3,a=1,b=2)
输出结果
(1, 2, 3)
{'a': 1, 'b': 2}
命名关键字参数(不明白)
# def foo(name,age,*,sex='male',height):
# print(name,age)
# print(sex)
# print(height)
# #*后定义的参数为命名关键字参数,这类参数,必须被传值,而且必须以关键字实参的形式去传值
# foo('egon',17,height='185')
补充:函数定义阶段到底干了什么事情:只检测函数体的语法,并不会执行
函数返回值
def foo():
print('from foo')
x=1
return 1,[2,3],(4,5),{}
res=foo()
print(res) #打印结果:(1,[2,3],(4,5),{})
a,b,c,d=foo()
print(a)
返回多个值的时候是一个元组,可以按顺序赋值
占位赋值
t=(1,2,3)
a,b,_=t
print(b)
t=(1,2,3,4,5,6,7,8,9)
a,*_,c=t
print(a)
print(c)
输出结果:
2
1
9