引用、递归函数、匿名函数、列表推导式、文件的读写、with open()as file文件的相关操作shutil模块和os模块
1.引用
什么是引用?
python中 值传递的一种方式,引用就是 容器 -- 物品之间 -- 对应关系(可以类比c的指针)
在python中,值是靠引用来传递来的。
python中变量保存的不是数值 而是引用
id 查看一个变量的地址 (唯一标识 就好比门牌号一样)
我们可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标示。
之前为了更好的理解变量,咱们可以把a=100理解为变量a中存放了100,事实上变量a存储是100的引用(可理解为在内存中的一个编号)
引用当做实参
可变类型与不可变类型的变量分别作为函数参数时,会有什么不同吗?
Python有没有类似C语言中的指针传参呢?
def test1(b): # 变量b一定是一个局部变量,就看它指向的是谁?可变还是不可变
b += b # += 是直接对b指向的空间进行修改,而不是让b指向一个新的
b = b+b # xx = xx+yyy 先把=号右边的结果计算出来,然后让b指向这个新的地方,不管原来b指向
# 谁, 现在b一定指向这个新的地方
总结:
Python中函数参数是引用传递(注意不是值传递)
对于不可变类型,因变量不能修改,所以运算不会影响到变量自身
■ b = b + b 和 b += b 都是属于重新赋值
而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量
■ 可变的数据类型 b = b + b 重新赋值 (b += b 对原来的数据进行修改)
2.递归函数
递归函数: 其函数内部调用其自己本身
如果一个函数在内部调用的函数是自己本身的话,这个函数就是递归函数。
在python中递归函数必须有一个停止递归调用的条件(因为调用函数的时候也需要消耗资源) 如果递归函数不能停止 就会把计算机资源耗尽
为了理解: 在递归函数中 自己调用自己本身 (只是函数名相同 但是存在于不同的空间)
import sys
获取递归次数
sys.getrecursionlimit()
设置递归次数n次
sys.setrecursionlimit(n)
3.匿名函数
用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
Lambda函数能接收任何数量的参数但只能返回一个表达式的值
匿名函数不能直接调用print,因为lambda需要一个表达式
匿名函数(藏匿名字的函数):
01: 对函数的另一种表现形式
■ 无参数无返回值的函数
f = lambda :print("你好世界")
■ 无参数有返回值的函数
f = lambda :3.14
■ 有参数无返回值的函数
f = lambda name:print("你好%s" % name)
■ 有参数有返回值的函数
f = lambda a, b: a + b
02: 可以作为函数的参数使用
f = lambda a, b, c : a + b + c
def average3num(num1, num2, num3, my_func):
# 求和
ret = my_func(num1, num2, num3)
# 返回
return ret / 3
# 变量
aa = 10
bb = 20
cc = 30
result = average3num(aa, bb, cc, f)
print(result)
03: 自定义排序 list.sort
列表.sort(key=lambda 临时变量名:临时变量名[key])
4.列表推导式
所谓的列表推导式,就是指的轻量级循环创建列表
01: 需求: 定义一个列表 保存1~100元素
list = [i for i in range(1, 101)]
02: 定义一个列表 保存10个元素 每个元素都为 "哈哈"
list = ["哈哈" for _ in range(10)]
03:定义一个列表 保存1~100直接的偶数
list = [i for i in range(1, 101) if i % 2 == 0]
04: [(0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3)]
list = [(i, j) for i in range(2) for j in range(1, 4)]
05:写出一段 Python 代码实现分组一个 list 里面的元素,比如 [1,2,3,...100]变成 [[1,2,3],[4,5,6]....] 切片技术: 字符串 列表
a = [x for x in range(1,101)]
b = [a[x:x+3] for x in range(0,len(a),3)]
5.文件的读写
不同的文件 有不同的后缀名(代表是不同类型的文件)
文件存在的意义? 为了保存数据(持久化) -> 硬盘
变量存在的意义? 保存数据 临时保存(程序运行中) -> 内存
就是把一些存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力
open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
file: 文件名 encoding: 编码格式 errors: 表示如果按照utf-8的编码格式进行解码时,可以在解码不出来时用errors='ignore'忽略特殊字符,保证程序不报错
<1>打开文件
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
open(文件名,访问模式)
访问权限:r 只读、w 只写、a 追加
文件的打开
默认情况下 使用r
如果文件存在 直接打开
如果文件不存在 将报错
open("hm.txt", "r")
使用w
如果文件存在 直接打开
如果文件不存在 先创建 然后再打开
open("hm.txt", "w")
使用a
如果文件存在 直接打开
如果文件不存在 先创建 然后再打开
open("hm1.txt", "a")
访问模式 说明
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
r+ 等同于 r+w,可不清空原内容
w+ 等同于 = w+r
a+ 等同于 = a+r
<2>关闭文件
close( )
示例:f.close()
如果程序员没有关闭文件 待程序退出后 系统会帮我们关闭
<3>写数据(write)
使用write()可以完成向文件写入数据
使用w默认打开文件 每次打开先进行清空数据
f = open("hm.txt", "w")
f.write("helloworld")
f.close()
使用a默认打开文件,在原有的数据后面 进行追加数据
f = open("hm.txt", "a")
f.write("haha")
f.close()
当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是在缓冲区(buffer),空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:
with open('test.txt', 'w', encoding='utf-8') as f:
f.write('Hello, world!')
<4>读数据(read)
■ f.read([size]) #size为读取的长度,以byte为单位,在rb(二进制)模式下,使用utf-8的编码格式时,一个汉字占用三个字节,一个字母占用一个字节
■ f.readline([size]) #读一行,如果定义了size,有可能返回的只是一行的一部分
■ f.readlines([size]) #把文件每一行作为一个list的一个成员,并返回这个list。其实它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。
■ f.write(str) #把str写到文件中,write()并不会在str后加上一个换行符
■ f.writelines(seq) #把seq的内容(元素是字符串的列表)全部写到文件中(多行一次性写入)。这个函数也只是忠实地写入,不会在每行后面加上任何东西。
■ f.close() #关闭文件。python会在一个文件不用后自动关闭文件,不过这一功能没有保证,最好还是养成自己关闭的习惯。 如果一个文件在关闭后还对其进行操作会产生ValueError
■ f.seek(offset[,whence]) #将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了,whence可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。
■ f.flush() #把缓冲区的内容写入硬盘
■ f.fileno() #返回一个长整型的"文件标签"
■ f.isatty() #文件是否是一个终端设备文件(unix系统中的)
■ f.tell() #返回文件操作标记的当前位置,以文件的开头为原点
■ f.next() #返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。
■ f.truncate([size]) #把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。如果size比文件的大小还要大,依据系统的不同可能是不改变文件,也可能是用0把文件补到相应的大小,也可能是以一些随机的内容加上去。
print(f.encoding) #查看编码格式
默认情况下 windows 编码格式为cp936 也就是GBK ascii
在mac和乌班图上编码格式默认就是utf-8格式
保存中文的时候 需要程序员指定编码格式为utf-8
f = open("hm.txt", "w", encoding="utf-8")
f.write("中国")
f.close()
<5>二进制读写数据(b)
rb 以二进制方式读取数据时:
文件访问模式里面如果带有b(binary二进制)模式,不需要指定编码格式,因为数据读取出来或者写入都需要进行解码和编码
content = result.decode('utf-8', errors='ignore')
errors: 表示如果按照utf-8的编码格式进行解码时,可以在解码不出来时用errors='ignore'忽略特殊字符,保证程序不报错
读取二进制数据进行解码(以utf-8的格式进行解码)操作:
result = f.read()
content = result.decode('utf-8')
print(content)
wb 以二进制方式写入数据时:
把字符(以utf-8的格式进行编码)转成二进制再写入
content = '你好'
content_data = content.encode('utf-8')
f.write(content_data)
或者:
f.write('a.txt', encode('utf-8'))
<6>在指定位置创建新文件
\:表示转义字符,两个反斜杠表示一个真正的反斜杠字符
file_path = 'C:\\Users\\Administrator\\Desktop\\' + newFileName
# 打开新文件
newFile = open(file_path, 'wb')
6.文件的相关操作shutil模块和os模块
<1>导入os模块
import os
文件、文件名重命名
os模块中的rename()可以完成对文件或文件名的重命名操作
os.rename(需要修改的文件名, 新的文件名)
os.rename("毕业论文.txt", "毕业论文-最终版.txt")
删除文件
os模块中的remove()可以完成对文件的删除操作
os.remove(待删除的文件名)
os.remove("毕业论文.txt")
创建文件夹
os模块中的mkdir()可以完成创建文件夹
os.mkdir(待创建的文件夹名)
os.mkdir("张三")
获取当前目录
os模块中的getcwd()可以获取当前目录,返回一个字符串类型的路径地址
os.getcwd()
path = os.getcwd()
print(path)
改变默认目录
os模块中的chdir()可以改变默认目录
./ 相对路径 == C:\北京黑马金32期代码\第九天的代码 (当前路径)
./黑马 == 黑马 当前路径下的黑马文件夹
../ 相对路径 == C:\北京黑马金32期代码 (上一级)
C:\北京黑马金32期代码 绝对路径(可以看到盘符)
os.chdir("../") 切换到上一级目录
os.chdir("黑马")或者os.chdir("./黑马") 切换到当前路径下的黑马文件夹
获取目录列表
os模块中的listdir()可以获取目录列表,返回一个目录列表
os.listdir("./")
list = os.listdir("./")
print(list)
删除文件夹
os模块中的rmdir()可以删除空文件夹
os.rmdir("文件夹名")
os.rmdir("黑马")
扩展
判断文件在当前地址是否存在
isExists = os.path.exists(sourceFileName)
获取文件的绝对路径
my_path = os.path.abspath('文件名')
获取绝对路径的文件名
file_name = os.path.basename('绝对路径')
获取文件名及文件后缀
file_name, extension_name = os.path.splitext('文件名')
既改文件夹名又改文件名
os.renames('原文件夹名/原文件名', '新文件夹名/新文件名')
<2>导入shutil模块
import shutil
删除文件夹及里面的所有文件
shutil.rmtree('文件夹名')