Python语言基础8。函数

引用、递归函数、匿名函数、列表推导式、文件的读写、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('文件夹名')

你可能感兴趣的:(Python语言基础8。函数)