文件处理与函数

文件的高级操作

三大模式

如果我们想要既读取又写入可以在r/w/a这三种模式后面加一个‘+’号,这样就能实现既读取又写入。

我们先讲一讲r+吧,我们在test.txt文件中先写入‘你好,世界’

with open('test.txt', 'r+', encoding='utf8') as fr:  ##当test.txt文件不存在时会报错
     data = fr.read()
     print(fr.writable())  # True  ##这个可以证明在r+模式下是可以进行写入操作的
     fr.write('x = 10')  ## 发现test.txt文件中的内容是:你好,世界x = 10 ,发现r+模式下写入操作是属于追加的操作的。

既然已经了解了r+,那让我们看看w+

with open('test.txt', 'w+', encoding='utf8') as fw:
    print(fw.readable())  # True ##这个可以证明在w+模式下是可以进行读取操作的
    fw.write('x = 10')  # x = 10 ##可以证明这个写入会清除之前的内容
    data = fw.read()  ##由于写入完成后指针是在最后面所以read()读取不到东西的
    print(data)  ##直接打印了个空行

还有一个就是a+

##可以想象a+也是可读可写,并且是在内容的最后写入,并不会删除之前的内容
with open('test.txt', 'a+', encoding='utf8') as fa:
    data = fa.read()  # 指针在末尾读取不到内容
    print(data)  # 一个空行
    fa.write('x = 10')  # 你好,世界x = 10

整理:

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

由于默认是以t模式打开,所以上面表格不在添加t

三大模式总结:

模式 r r+ w w+ a a+
+ + + +
+ + + + +
创建 + + + +
覆盖 + +
指针在开始 + + + +
指针在结尾 + +

文件对象的方法

读取:read()

with open("test.txt", "r", encoding="utf-8") as fr:
    str = fr.read()
    print(str)  ## 以字符串的形式输出文件中的内容
    str = fr.read(5)
    print(str)  ## 输出文件前五个字符 

读取一行:readline()

with open("test.txt", "r", encoding="utf-8") as fr:
    str = fr.readline()
    print(str)  ## 以字符串的形式输出文件中第一行的内容

读取所有行:readlines()

with open("test.txt", "r", encoding="utf-8") as fr:
    str = fr.readlines()
    print(str)  # ['你好,世界
', 'x = 10']  ## 返回一个字符串列表,列表每个元素都是一行的内容

还有一个方式是直接迭代文件对象

with open("test.txt", "r", encoding="utf-8") as fr:
    for i in fr:
        print(i,end='')  #你好,世界
						 #x = 10

按字节位移:seek()

  • seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
  • seek(x,1) : 表示从当前位置往后移动x个字符
  • seek(-x,2): 表示从文件的结尾往前移动x个字符
with open('test.txt', 'rb+') as f:
    f.write(b'0123456789abcdef')
    f.seek(5)  # 移动到文件的第六个字节
    str = f.read(1)  # 读取文件1个字节的内容
    print(str)  # b'5'
    f.seek(-3, 2)  # 移动到文件的倒数第三字节
    str = f.read(1)
    print(str)  # b'd'

返回指针所处的位置:tell()

with open('test.txt', 'r', encoding='utf8') as fr:
    fr.seek(2, 0)  # 从文件头左移两个字节
    print(fr.tell())  # 2

截取字节:truncate()

with open('test.txt', 'rb+') as f:
    f.write(b'0123456789abcdef')
    f.truncate(7)  # 截取前七个字符 文件中只留:0123456

文件修改的两种方式

方式一:

将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘

import os
with open('37r.txt') as fr,open('37r_swap.txt', 'w') as fw:
    data = fr.read()  # 全部读入内存,如果文件很大,会很卡
    data = data.replace('tank', 'tankSB')  # 在内存中完成修改

    fw.write(data)  # 新文件一次性写入原文件内容

# 删除原文件
os.remove('37r.txt')
# 重命名新文件名为原文件名
os.rename('37r_swap.txt', '37r.txt')

方式二:

将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件。

import os
with open('37r.txt') as fr,open('37r_swap.txt', 'w') as fw:
    # 循环读取文件内容,逐行修改
    for line in fr:
        line = line.replace('jason', 'jasonSB')
        # 新文件写入原文件修改后内容
        fw.write(line)

os.remove('37r.txt')
os.rename('37r_swap.txt', '37r.txt')

函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。

函数的定义方式

语法

def 函数名(参数列表):
    函数体

定义规则

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

示例:

def hello() :
   '''程序员的第一个语句'''
   print("Hello World!")
hello()  # Hello World!  ## 调用函数,执行函数内的代码
print(hello.__doc__)  # 程序员的第一个语句

函数的分类

空函数

def login():  ## 定义了一个函数但是没有去实现他的功能
	pass

无参函数

def pr_Hello():  ## 定义了一个不需要传递参数的函数
	print("Hello World!")

有参函数

def sum_number(num1,num2):  ## 定义了一个需要两个参数的函数,在调用该函数的时候需要传递两个参数
	print(num1+num2)

参数

  • 形参: 定义阶段才有形参,形式参数,啥也没用,只是占个位置,具有描述意义

  • 实参: 调用阶段才有实参,实际的参数,具有具体的值

  • 必需参数

  • 关键字参数

  • 默认参数

  • 不定长参数

必须参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

调用 sum_number() 函数,你必须传入一个参数,不然会出现语法错误

def sum_number(num1,num2):  ## 定义了一个需要两个参数的函数,在调用该函数的时候需要传递两个参数
	print(num1+num2)
    
sum_number()  # sum_number() missing 2 required positional arguments: 'num1' and 'num2'

关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致。但是必须参数必须在关键字参数之前

def printme(name, age):
   '''打印姓名年龄'''
   print(f'{name}——{age}')  

printme('Gredae', age = 18)  # Gredae——18

默认参数

调用函数时,如果没有传递参数,则会使用默认参数。

def printme(name, age = 18):
   '''打印姓名年龄'''
   print(f'{name}——{age}')  

printme('Gredae')  # Gredae——18
printme('nick',32)  # nick——32

不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。

加了星号 ***** 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。

def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print ("输出: ",arg1,vartuple)
 
# 调用printinfo 函数
printinfo( 70, 60, 50 )  # 输出: 70 (60,50)
printinfo( 10 )  # 输出: 10  ##如果在函数调用时没有指定参数,它就是一个空元组

还有一种就是参数带两个星号 **,加了两个星号 ** 的参数会以字典的形式导入。

def printinfo( arg1, **vardict ):
   "打印任何传入的参数"
   print ("输出: ",arg1,vartuple)
 
# 调用printinfo 函数
printinfo(1, a=2,b=3)  # 输出: 1 {'a': 2, 'b': 3}

return 语句

def sum_number( num1, num2 ):
   total = num1 + num2
   print ("函数内输出 : ", total)  # 函数内输出 : 30
   return total  ## 用于函数的返回并终止函数,可以返回任意数据类型,当返回多个值时默认以元组的形式返回
 
# 调用sum_number函数
total = sum_number( 10, 20 )
print ("函数外输出 : ", total)  # # 函数外输出 : 30
原文地址:https://www.cnblogs.com/Gredae/p/11322177.html