3.17
上节课复习
-
x模式,只写模式,不存在则创建,存在则报错
-
b 模式:以bytes为单位读写,可以操作所有文件,一定不能指定encoding
-
操作:f.read() 得到二进制,python针对二进制封装得到bytes类型,显示的都是bytes
-
要想在b模式得到字符,要手动解码编码
res.decode('utf-8')
-
看到bytes类型,就把他当作二进制
bytes转二进制:
- b’英文字符’ 字符串前面加b
- 字符串编码之后的结果:’上’.encode(‘utf-8’)
- b 模式下打开文件,f.read 读出内容
-
readline(),readlines(),read(n)
防止一次读取文件过大占用过多内存,指定长度读取或循环读取文件
while True: line = f.read(1024) if len(line) == 0: break
-
f.seek(n,mode)
- 0 模式:相对文件开头
- 1 模式:相对于当前指针位置
- 2 模式:相对于文件末尾
今日内容
- tail -f access.log
- 文件修改的两种方式
- 函数
- 函数参数
正课
tail-f
Linux中命令,动态查看文件变化,用于纪录日志
需求:读末尾新加的数据,需先将指针跳到文件末尾:f.seek(0,2)
import time
with open('access.log',mode = 'rt',encoding = 'utf-8') as f:
f.seek(0,2)
f.readline()
while True:
line = f.readline() # 从最末尾,新加入内容之前的位置,往后读
if len(line) == 0:
time.sleep(0.3) # 睡0.3秒,防止一直死循环
else:
print(line)
注意只有在 b 模式下才搭配使用 seek ,因为b 模式以字节为单位编写,移动指针才有意义
文件修改的两种方式
我们在改文件时,在源文件里新增,新增后面的部分都往后平移。但是在硬盘上实际上这样修改,会把后面同等长度的字节覆盖。硬盘上的数据没有改 这一说,都是用新的覆盖老的
在文本编辑器上修改,保存后实际上是使用内存上的内容覆盖回硬盘
方式1 文本编辑器
with open('c.txt','r',encoding = 'utf-8') as f:
res = f.read
修改
with open('c.txt','w',encoding = 'utf-8') as g:
g.write(res)
-
占用内存大,要把整个文件放进内存
-
不占硬盘空间
方式2
import os
with open('c.txt','r',encoding = 'utf-8') as f,
open('.c.txt.swap','wt',encoding = 'utf-8') as f1:
for line in f:
f1.write(line.replace(''))
os.remove('c.txt')
os.rename('.c.txt.swap','c.txt')
创造一个新文件,删除旧文件,将新文件名命名为旧文件
- 占用硬盘空间,不占用内存空间
函数
什么是函数
- 相当于具备某一功能的工具
- 函数的使用必须遵循一个原则:先定义后使用
为什么要用函数
- 代码冗余,程序组织结构不清晰,可读性差
- 可维护性,可扩展性差
如何用函数
先定义
定义函数发生的事情:
- 申请内存空间,保存函数体代码
- 将上输内存地址绑定给函数名
- 定义函数不会执行函数体代码,但会检测其语法
调用函数发生的事情:print(函数名),得到函数体的内存地址
- 通过函数名找到函数的内存地址
- 通过加括号就是在触发函数体代码的执行
函数的嵌套,在定义的时候不管其中嵌套的函数有没有被定义,只检测语法,此时调用的函数没有被定义也不会报错。在真正执行该函数的时候,才会去看这个被嵌套的函数有无被定义
def foo():
bar() # 此时只检测语法,不管有没有定义
print('from foo')
def bar(): # bar=函数的内存地址
print('from bar')
foo()
定义的语法
def 函数名(参数1,参数2,...):
'''文档描述'''
函数体
return 值
- 必须要有:def,函数名,括号,冒号,函数体
- 可以没有:参数,返回,文档描述
- 函数名的命名规则与变量名一样,更多地应该命名成动词
-
定义形式1 无参函数
def func(): pass # 定义无参函数 # 调用 func()
-
定义形式2 有参函数
def func(x,y): print(x,y) # 定义有参函数 # 调用的时候,也要传入参数 func(1,2)
-
定义形式3 空函数
函数体代码为pass,...,不执行任何操作
三种定义形式各有其用处
函数相当于一个工厂,函数体相当于加工的模板流程,参数相当于加工的原材料,返回值相当于工厂的产品
各个工厂干的活不一样,有些工厂必须要原材料才能运行,有些工厂不需要原材料,有工厂不产生产品
- 无参 / 有参 数函数的应用场景:写死 / 不写死功能
- 空函数的应用场景:构思代码的时候,编程写框架的时候
调用函数
-
语句的形式,只加括号调用,不做其他操作
func(x,y)
-
表达式形式,
res = func(x,y) # 赋值表达式 func(x,y) * 10 # 数学表达式
-
函数调用可以当作参数
func(func(1,2),y) # 实际上传入的参数是func(1,2)的返回值和y
函数返回值
函数经过运算产生的产品
return 是函数结束的标志,函数体代码一旦运行到 return,会立刻终止运行,并且会将return 后的值当作本次运行的结果返回:
-
返回 none:没有 return 或着return 后面什么也没有
-
返回一个值:
return value
-
返回多个值:
用逗号分隔开多个值,会被 return 转成元组返回
return 10,'aa',[1,2] # 得到(10,'aa',[1,2])