今日概要
- 编码详解
- 文件操作
- 初识函数
一、字符编码
1、代码执行过程
代码-->解释器翻译-->机器码-->执行
2、ASCII
ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符)
后来为了将拉丁文也编码进了ASCII表,将最高位也占用了
3、GBK
GBK::2Bytes代表一个字符
日本把日文编到
Shift_JIS
里,韩国把韩文编到
Euc-kr
里
4、Unicode(万国码)
至少2Bytes代表一个字符, 2**16-1=65535,可代表6万多个字符,因而兼容万国语言
5、UTF-8
UTF-8,对英文字符只用1Bytes表示,对中文字符用3Bytes
6、unicode和uft-8的优缺点
unicode处理速度快,字符转换数字快,缺点占用空间多(无论字母或者中文都是2bytes)
uft-8的优点占用空间小,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示
7、unicode和utf-8的注意事项
- 内存中使用的编码是unicode,用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)硬盘中或者网络传输用utf-8,网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。
8、python程序执行过程
1、启动python解释器
2、解释器打开文本编辑器,从硬盘中读取内容到内存
3、读取已经加载到内存的代码(unicode编码的二进制),然后进行执行,执行的过程中可能开辟新的内存空间,比如x='dragon'
notice:
不是所有在内存的编码都是unicode
x = 'dragon'在内存的编码是unicode,此时将代码换成x = 'dragon'.encode('utf-8'),那么新申请的内存空间里存放为utf-8编码
详细过程图如下:
9、打开网页过程
打开网页服务器会把动态生成的unicode内容转换为utf-8在传给浏览器,如何服务端encode编码格式为utf-8,客户端内存中接收到的utf-8编码的二进制
10、python2中编码区别
在python2中,str就是编码后的结果bytes,str=bytes,所以在python2中,unicode字符编码的结果是str/bytes
#-*- coding:utf-8 -*-
s='牛' #在执行时,'牛'会被以conding:utf-8的形式保存到新的内存空间中
print repr(s) #'\xe6\x9e\x98' 三个Bytes,证明确实是utf-8
print type(s) #<type 'str'>
s.decode('utf-8')
# s.encode('utf-8') #报错,因为s的编码为bytes,只能decode
unicode类型
当python解释器执行到产生字符串的代码时(例如s=u'牛'),会申请新的内存地址,然后将'牛'以unicode的格式存放到新的内存空间中,所以s只能encode,不能decode
s=u'牛'
print repr(s) #u'\u6797'
print type(s) #<type 'unicode'>
# s.decode('utf-8') #报错,s为unicode,所以只能encode
s.encode('utf-8')
二、文件操作
1、文件处理的基本流程
(1)打开文件,得到文件句柄并赋值给一个变量
(2)通过文件句柄对文件进行操作
(3)关闭文件,释放内存
f = open('cashi') #打开文件
first_line = f.readline() #读取一行 readlines读取全部返回一个list
data = f.read()# 读取剩下的所有内容,文件大时不要用
print(data) #打印读取内容
f.close() #关闭文件
2、打开文件几种操作方式
打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。
打开文件的模式有:
- r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
- w,只写模式【不可读;不存在则创建;存在则清空内容】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【可读; 不存在则创建;存在则只追加内容】
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】
- w+,写读【可读,可写】
- x+ ,写读【可读,可写】
- a+, 写读【可读,可写】
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
3、buffer和cache的区别
写入文件的操作也都是存入内存缓冲区buffer(内存速度快于硬盘,如果写入文件的数据都从内存刷到硬盘,内存与硬盘的速度延迟会被无限放大,效率变低,所以要刷到硬盘的数据我们统一往内存的一小块空间即buffer中放,一段时间后操作系统会将buffer中数据一次性刷到硬盘)
4、flush-将写入数据刷入硬盘
import time
with open('3.txt','w+',encoding='utf-8') as f :
for i in range(10):
f.write(str(i))
f.flush()
time.sleep(0.5)
5、文件的光标移动,seek,tell,read,truncate
read(3)代表读取3个字符,其余的文件内光标移动都是以字节为单位如seek,tell,read,truncate
f.seek(3) #seek内指定的数字代表字节
seek(3) #默认情况,是以文件起始位置作为开始,往后移动3个bytes
seek(2,1) #1 代表以当前光标所在的位置为开始,往后移动2个 bytes
seek(-1,2) #2表以当前光标所在的位置为开始,往后移动2个 bytes
tell() #当前光标所在的位置
truncate清空文件
6、with上下文管理器
with open('a.txt','r',encoding='utf-8') as f
print(f.read())
print('====>')
#这样就不需要进行f.close()关闭文件句柄
7、模拟tailf模式看access日志
import time
with open('access.log','r',encoding='utf-8') as f:
f.seek(0,2)
while True:
line = f.readline().strip()
if line:
print('-----',line)
time.sleep(0.5)
8、文件修改
#文件修改
import os
read_f = open('b.txt','r',encoding='utf-8')
write_f = open('.swp.b.txt','w',encoding='utf-8')
for line in read_f.readlines():
if line.startswith('1111'):
line = '2222222\n'
write_f.write(line)
read_f.close()
write_f.close()
os.remove('b.txt')
os.rename('.swp.b.txt','b.txt')
三、初识函数
1、无函数的代码
(1)无结构,可读性差
(2)代码冗余特别高
2、python函数,定义方法
python中函数定义方法:
def test(x):
"The function definitions"
x+=1
return x
def:定义函数的关键字
test:函数名
():内可定义形参
"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值
3、python函数分类
1、内置函数
#python自带的内置函数,直接调用就可以
max
min
a=len('dragon')
print(a)
b=max([1,2,3])
print(b)
2、自定义函数
1.无参数函数
#自定义函数
def print_star():
print('#'*6)
def print_msg():
print('hello world')
#函数调用
print_star()
print_msg()
2.有参数函数
1.位置参数-位置实参与形参一一对应
位置参数
def foo(x,y,z):#位置形参:必须被传值的参数
print(x,y,z)
# foo(1,2,3)
foo(1,2,3) #位置实参数:与形参一一对应
2.关键字参数
注意事项
1:关键字实参必须在位置实参后面
2: 不能重复对一个形参数传值
关键字参数:key=value
def foo(x,y,z):
print(x,y,z)
foo(z=3,x=1,y=2)
foo(1,z=3,y=2) #正确
foo(x=1,2,z=3) #错误
foo(1,x=1,y=2,z=3)
3.默认参数
#默认参数
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)
#三:默认参数的值通常定义成不可变类型
4.可变长参数(*args,**kwargs)
*会把溢出的按位置定义的实参都接收,以元组的形式赋值给args
**会把溢出的按关键字定义的实参都接收,以字典的形式赋值给kwargs
def foo(x,y,*args):
print(x,y)
print(args)
foo(1,2,3,4,5)
def add(*args):
res=0
for i in args:
res+=i
return res
print(add(1,2,3,4))
print(add(1,2))
def foo(x, y, **kwargs):
print(x, y)
print(kwargs)
foo(1,2,a=1,name='egon',age=18)
5.命令关键字参数
def foo(name,age,*,sex='male',height):
print(name,age)
print(sex)
print(height)
#*后定义的参数为命名关键字参数,这类参数,必须被传值,而且必须以关键字实参的形式去传值
foo('egon',17,height='185')
def foo(name,age=10,*args,sex='male',height,**kwargs):
def foo(name,age=10,*args,sex='male',height,**kwargs):
print(name)
print(age)
print(args)
print(sex)
print(height)
print(kwargs)
foo('alex',1,2,3,4,5,sex='female',height='150',a=1,b=2,c=3)
3.空函数
def delete():
pass
def insert()
pass
4、函数的调用
#!/usr/bin/python
# -*- coding:utf-8 -*-
def foo():
print('from foo')
def bar(name):
print('bar===>',name)
#按照有参和无参可以将函数调用分两种
foo() #定义时无参,调用时也无需传入参数
bar('egon') #定义时有参,调用时也必须有参数
#按照函数的调用形式和出现的位置,分三种
foo() #调用函数的语句形式
def my_max(x,y):
res=x if x >y else y
return res
# res=my_max(1,2)*10000000 #调用函数的表达式形式
# print(res)
res=my_max(my_max(10,20),30) #把函数调用当中另外一个函数的参数
print(res)
5、三元运算
#正常方法
x=10
y=2
if x > y:
print(x)
else:
print(y)
#简化版方法
res=x if x > y else y
print(res)