一、递归函数

递归函数可以在函数主体内直接或间接的调用自己,即函数的嵌套时函数本身。递归是一种程序设计方法,使用递归可以减少重复的代码,使程序变得简洁。递归的过程分为两个阶段——递推和回归。递归函数的原理如下:

第一阶段,递归函数在内部调用自己。每一次函数调用又重新开始执行此函数代码,直到某一级递归程序结束。

第二阶段,递归函数从后往前返回。递归函数从最后一级开始返回,一直返回到第一次调用的函数体内。即递归逐级调用完毕后,再按照相反的顺序主机返回。

递归函数需要编写递归结束条件;否则,递归程序将无法结束。一般通过判断语句来结束程序。

练习(是用递归实现阶乘):

#用递归实现1-6的阶乘
def mul(n):
    if(n>1):
        return n*mul(n-1)
    else:
        return 1

result = mul(6)
print(result)

注意:每次调用递归函数都会复制函数中所有变量,再执行递归函数。程序需要较多的存储空间,对程序性能会有一定影响。因此,对于没有必要进行的递归程序,最好用其他的方法进行改进

递归程序在实现时依靠栈这种数据类型,在递推过程中,调用自己之前将当前环境变量当前数据压入栈内,递推到最后返回时,逐级将栈中数据弹出,这样就是实现的递归过程中的存储。

可以使用reduce()函数快速实现阶乘的运算

from functools import reduce
print("5!=",reduce(lambda x,y:x*y,range(1,6)))

二、匿名函数

lambda函数用于创建一个匿名函数,函数名未知标识符进行绑定。使用lambda函数可以返回一些简单的运算结果。lambda函数的格式如下所示:

lambda 变量2,变量2...:表达式

其中,变量列表用于表达式计算。lambda属于函数,因此变量列表后需要一个冒号。通常把lambda赋值给一个变量,变量就可以作为函数使用。例如:

func = lambda 变量1,变量2...:表达式
func()

这样就把lambda和变量func绑定在一起了,变量func的名称就是函数名。注意,lambda中只能使用表达式,不能使用判断、循环等多重语句。

三、文件

程序在运行过程当中,数据都在内存中,在下次运行程序时,之前的数据不会被保存下来,如需保存程序运行时的数据,则需要引入文件对程序数据进行保存。

数据的存储可以使用数据库,也可以使用文件。数据库保持了数据的完整性和关联性,而且使数据更安全、可靠。使用文件存储数据则非常简单、易用,不必安装数据库管理系统等运行环境。文件通常用于存储应用软件的参数或临时性数据。

1.文件的常见操作

文件通常用于存储数据或应用系统的参数。python提供了os、os.path、shutil等模块处理文件,其中包括打开文件、读写文件、复制文件和删除文件等函数。

1.1文件的创建

文件的打开或创建可以使用open()函数,该函数可以指定处理模式。

文件的打开模式:

  • r 以只读的方式打开文件
  • r+ 以读写的方式打开文件
  • w 以写入的方式打开文件。先删除文件原有的内容,再重新写入新的内容。如果文件不存在,则创建1个新的文件。
  • w+以读写的方式打开文件。先删除文件原有的内容,再重新写入新的内容。如果文件不存在,则创建1个新的文件。
  • a 以写入的方式打开文件,在文件的末尾追加新的内容。如果文件不存在,则创建一个新的文件。
  • a+ 以读写的方式打开文件,在文件的末尾追加新的内容。如果文件不存在,则创建一个新的文件。
  • b 以二进制模式打开文件。可与r、w、a、+结合
    注意,对于图片、视频等文件必须使用“b”的模式读写。

1.2.file类的常用属性和方法

(1)close() 关闭文件

(2)read([size]) 从文件中读取size个字节的内容,作为字符串返回

(3)readline([size]) 从文件中读取一行,作为字符串返回。如果指定size,表示每行每次读取的字节数,依然要读完整行的内容。

(4)readlines([size]) 把文件中的每行存储在列表中返回。如果指定size,表示每次读取的字节数。

(5)seek(offset[,whence]) 把文件的指针移动到一个新的位置。offset表示相对于whence的位置。whence用于设置相对位置的起点,0表示从文件的开头开始计算;1表示从当前位置开始计算;2表示从文件末未开始计算。如果,whence省略,offset表示相对文件开头的位置。

(6)tell() 返回文件指针的当前位置。

(7)write(str) 把字符串str的内容写入文件。

1.3.文件的处理一般分为3个步骤:

(1)创建并打开文件,使用file()函数返回个file对象。

(2)调用file对象的read()、write()等处理文件。

(3)调用close()关闭文件,释放file对象占用的资源。

close()方法是必要的,虽然python提供了垃圾回收机制,清理不再使用对象,但是手动释放不再需要的资源是一种良好的习惯。同时也显示地告诉python垃圾回收器,该对象需要被删除。

1.4.文件的读取

(1)按行读取方式readline()

readline()每次读取文件中的一行,需要使用永真表达式循环读取文件。但当文件指针移动到文件的末尾时,依然使用radline()读取文件将会出现错误。因此程序中需要添加1个判断语句,判断文件指针是否移动到文件的尾部,并通过该语句中断循环。

f = open("test.txt")
while True:
    line = f.readline()
    if line:
        print(line)
    else:
        break
f.close()

(2)多行读取方式readlines()

使用readlines()读取文件,需要通过循环访问readlines返回列表中的元素。函数readlines()可一次性读取文件中的多行数据。

(3)一次性读取方式read()

读取文件最简单的方法是使用read(),read()将从文件中一次性读出所有内容,并赋值给一个字符串变量。

1.5.文件的写入

文件的写入使用write()方法

1.6.文件的重命名

os模块的函数rename()可以对文件或目录进行重命名。

练习(文件重命名):

#f.tell()表示文件指针的当前位置
#f.seek(a,b)文件的随机读写b=0/1/2,0表示文件开头,1表示当前位置,2表示文件结尾,a表示从指定位置出向后定位a位
#文件批量重命名
import os

#提示用户输入要重名的文件名
need_rename = input("请输入要重命名的文件名")
all_file_name = os.listdir("./"+need_rename)
print(all_file_name)

for file_name in all_file_name:
    find_pos = file_name.rfind(".")
    new_name = file_name[:find_pos]+"new"+file_name[find_pos:]
    print(new_name)
    os.rename("./"+need_rename+"/"+file_name,"./"+need_rename+"/"+new_name)#重命名时一定要注意文件的路径
    print("重命名成功!")

new_file_name = os.listdir("./test")

练习(删除文件名前缀):

import os

need_rename = input("请输入要删除前缀的文件名:")
need_renames = os.listdir("./"+need_rename)
remain_name = input("请输入要保留的第一个字:")

for name in need_renames:
    del_prio_name = name.rfind(remain_name)
    new_name = name[del_prio_name:]
    os.rename("./"+need_rename+"/"+name,"./"+need_rename+"/"+new_name)

new_list = os.listdir("./"+need_rename)
print(new_list)

四、练习

练习一(实现文件复制并重命名):

#文件复制
#提示用户要复制的文件名
name = input("请输入要读取的文件名:")

#打开文件1
f1 = open(name,"r")
#找到文件名中.的位置
post_pos = name.rfind(".")
#创建新的文件名
new_name =name[:post_pos]+"[复制]"+name[post_pos:]
print(new_name)

#打开文件2
f2 = open(new_name,"w")

#方式1
#存储文件1内容
#str_of_f1 = f1.read()
#将文件1读出的内容写入文件2
#f2.write(str_of_f1)

#方式2
#文件1按行读取,再写入文件2中
#for content in f1.readlines():
   # f2.write(content)

#方式3
while(True):
    str = f1.readline()
    if (len(str)):#判断读取出的内容是否为空
        f2.write(str)
    else:
        break

print("文件读写完毕!!")
#关闭文件1和文件2
f1.close()
f2.close()
#读取并输出复制文件的内容
f=open(new_name,"r")
print("复制的文件名为",new_name)
print("内容为:")
print(f.read())
f.close()

练习2(实现学生管理系统的数据文件保存):

#学生信息管理系统
names =  []
#打印输出界面信息
def print_info():
    print("=" * 30)
    print("1:添加学生信息")
    print("2:删除学生信息")
    print("3:修改学生信息")
    print("4:查询学生信息")
    print("5:保存学生信息")
    print("0:退出系统")
    print("=" * 30)

#获取键入的学生信息
def get_infor():
    new_name = input("请输入学生的名字:")
    new_sex = input("请输入学生的性别:")
    new_high = input("请输入学生的身高:")
    return {"name":new_name,"sex":new_sex,"high":new_high}

#添加学生信息
def add_info():
    result = get_infor()
    student_info = {}
    student_info["name"] = result["name"]
    student_info["sex"] = result["sex"]
    student_info["high"] = result["high"]
    names.append(student_info)
    print("添加成功!")

#删除学生信息
def del_info():
    name = input("请输入要删除的学生姓名:")
    for name_check in names:
        if (name_check["name"] == name):
            names.remove(name_check)
            break
    print(names)
    print("删除成功!")

#修改学生信息
def update_info():
    result = get_infor()
    for name_check in names:
        if (name_check["name"] == result["name"]):
            break
    name_check["name"] = result["name"]
    name_check["sex"] = result["sex"]
    name_check["high"] = result["high"]
    print("修改成功!")

#查询学生信息
def check_info():
    name = input("请输入要查询的名字:")
    for name_check in names:
        if (name_check["name"] == name):
            flag = 1
            break
    if (flag == 1):
        print("查找成功!")
        print("   姓名     性别     身高")
        print("   %s    %s      %s" % (name_check["name"], name_check["sex"], name_check["high"]))

#保存文件信息
def save_file():
    f = open("student.data","w")
    f.write(str(names))
    f.close()

    # f = open("student.data", "r")
    # content = f.read()
    # list = eval(content)#将读出的文件字符串转换为其数据本来的类型
    # print(list)

#恢复数据
def recover_data():
    global names#全局变量在函数中使用时为了避免不必要的bug,一定在使用全局变量的时候用global关键字声明
    f = open("student.data","r")
    content = f.read()
    names = eval(content)
    f.close()

def main():
    #恢复数据
    recover_data()
    print(names)
#系统提示
    while(True):
        print_info()
#获取操作数字
        op = input("请输入你要进行的操作:")
#根据用户选择进行功能调用
        flag = 0
        if(op == "1"):
            add_info()
        elif(op == "2"):
            del_info()
        elif(op == "3"):
            update_info()
        elif(op == "4"):
            check_info()
        elif(op == "5"):
            save_file()
        elif(op == "0"):
            exit(0)
main()