Python第四篇 Python函数及文件操作
第一章 函数介绍
1.1 函数介绍
-
函数介绍
函数就是将一段具有独立功能的代码块 整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求,就是方法
-
函数定义
def 函数名(参数): 代码1 代码2 ......
-
函数的调用
① 不同的需求,参数可有可无
② 一定是先定义函数,后调用函数
函数名(参数)
-
函数的参数
① 形参:函数定义时书写的参数(非真实数据)
② 实参:函数调用时书写的参数(真实数据)
# 定义函数时同时定义了接收用户数据的参数a和b,a和b是形参 def add_num2(a, b): print(a + b) # 调用函数时传入了真实的数据10 和 20,真实数据为实参 add_num2(20, 20)
-
函数的返回值
def add_num2(a, b): return a + b # 使用变量保存函数返回值 sum1 = add_num2(20, 20) print(sum1)
-
函数的文档注释
# 定义文档注释 def 函数名(参数): """ 说明文档的位置 """ 代码 ......
① 函数的文档注释的查看
# help(函数名) # 查看print()函数的文档注释 help(print()) # 查看有返回值的函数的文档注释 def add_num2(a, b): """" 求和函数 """ return a + b help(add_num2)
1.2 函数变量的作用域
-
变量作用域
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量
-
局部变量
定义:所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效
作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
-
全局变量
定义:所谓全局变量,指的是在函数体内、外都能生效的变量
作用:在全局生效
-
函数体内修改全局变量
a = 100 def testA(): print(a) def testB(): # global 关键字声明a是全局变量 global a a = 200 print(a) testA() # 100 testB() # 200 print(f'全局变量a = {a}') # 全局变量a = 200
-
global
全局变量的使用注意事项
在函数中不使用global声明全局变量时不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据
① 如果全局变量是可变类型,即使不在函数中使用global声明,也可以使用和修改其值
② 如果全局变量是可变类型,并且没有在函数中用global声明,是不能直接用‘=’赋值的,用‘=’赋值会被认为是把右边的值赋给一个与全局变量同名的局部变量 -
可变类型和不可变类型
① 可变类型:set(集合)、list(列表)、dict(字典)
② 不可变类型: int(整型)、string(字符串)、tuple(元组)
1.3 函数的返回值
-
return 关键字
注意:return 可以退出当前函数,导致 return 下方的代码不执行,只执行第一个 return
def return_num(): return 1 return 2 result = return_num() print(result) # 1
-
多个返回值
注意:函数可以返回多个数据的,默认是元组类型,也可以是:列表、元组或字典
def return_num(): return 1, 2 result = return_num() print(result) # (1, 2)
1.4 函数的参数
-
位置参数
调用函数时根据函数定义的参数位置来传递参数
注意:传递和定义参数的顺序及个数必须一致
def user_info(name, age, gender): print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}') user_info('TOM', 20, '男')
-
关键字参数
函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
def user_info(name, age, gender): print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}') user_info('Rose', age=20, gender='女') user_info('小明', gender='男', age=16)
-
缺省参数
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值
def user_info(name, age, gender='男'): print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}') user_info('TOM', 20) user_info('Rose', 18, '女')
-
不定长参数
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便
① 包裹位置传递
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递
def user_info(*args): print(args) # ('TOM',) user_info('TOM') # ('TOM', 18) user_info('TOM', 18)
② 包裹关键字传递
注意:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程
def user_info(**kwargs): print(kwargs) # {'name': 'TOM', 'age': 18, 'id': 110} user_info(name='TOM', age=18, id=110)
1.5 拆包和交换变量值
-
拆包:使用变量接收函数的返回值元素或者元组、字典的元素,数量必须一致
① 元组
def return_num(): return 100, 200 num1, num2 = return_num() print(num1) # 100 print(num2) # 200
② 字典
dict1 = {'name': 'TOM', 'age': 18} a, b = dict1 # 对字典进行拆包,取出来的是字典的key print(a) # name print(b) # age print(dict1[a]) # TOM print(dict1[b]) # 18
-
交换变量值
通常情况下,交换两个变量值,需要通过中间变量,但是
python
有更好的解决办法① 方法一:中间变量
# 1. 定义中间变量 c = 0 # 2. 将a的数据存储到c c = a # 3. 将b的数据20赋值到a,此时a = 20 a = b # 4. 将之前c的数据10赋值到b,此时b = 10 b = c print(a) # 20 print(b) # 10
② 方法二:python语法
a, b = 1, 2 a, b = b, a print(a) # 2 print(b) # 1
-
引用
在python中,值是靠引用来传递来的,
id()
是内存地址的标识,可以用来来判断两个变量是否为同一个值的引用注意:
id()
的类型为<class 'int'>
dict1 = {'01': 'a'} print(f'dict1的值为{dict1},地址为{id(dict1)}') # dict1的值为{'01': 'a'},地址为4340710080 dict1['02'] = 'b' print(dict1) # {'01': 'a', '02': 'b'} print(f'dict1的值为{dict1},地址为{id(dict1)}') # dict1的值为{'01': 'a', '02': 'b'},地址为4340710080
-
可变与不可变
数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变:数据修改前
id()
的值是否发生变化① 可变类型
列表、字典、集合
② 不可变
整形、浮点型、字符串、元组
1.6 常用的数学计算
-
简单的数学计算
# 求绝对值 abs(-10) # 10 # 数字的四舍五入计算 round(1.2) # 1
1.7 高阶函数
-
什么是高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现,函数式编程就是指这种高度抽象的编程范式
-
函数式编程的特点
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快
-
绝对值相加
# 需求:任意两个数字,按照指定要求整理数字后再进行求和计算 # 方法一: def add_num(a, b): return abs(a) + abs(b) result = add_num(-1, 2) print(result) # 3 # 方法二: def sum_num(a, b, f): return f(a) + f(b) result = sum_num(-1, 2, abs) print(result) # 3
-
内置的高阶函数
① map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回
# 需求:计算 list1 序列中各个数字的2次方 list1 = [1, 2, 3, 4, 5] def func(x): return x ** 2 result = map(func, list1) print(result) # <map object at 0x0000013769653198> print(list(result)) # [1, 4, 9, 16, 25]
② reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算
# 需求:计算 list1 序列中各个数字的累加和 import functools list1 = [1, 2, 3, 4, 5] def func(a, b): return a + b result = functools.reduce(func, list1) print(result) # 15
③ filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def func(x): return x % 2 == 0 result = filter(func, list1) print(result) # <filter object at 0x0000017AF9DC3198> print(list(result)) # [2, 4, 6, 8, 10]
第二章 文件操作
2.1 文件操作介绍
-
Python的文件操作
Python
的文件操作相比Java
简单了不少,其实操作简单只能代表封装太多,用起来更便捷,但是你知道的原理也就更少了 -
文件的读、写操作
① 文件打开
# 文件打开,如果没有文件则创建文件,仅限在 mode='w' 模式下 f = open('/Users/kylewhite/Downloads/a.txt', 'w')
② 文件读取
# read():选择性读取 f = open('/Users/kylewhite/Downloads/a.txt', 'r') # 10 表示要从文件中读取的数据的长度(单位是字节),如果没有传入值,那么就表示读取文件中所有的数据 f.read(10) # 读取全部内容 f.read()
# readlines():一次读取所有行数据 # 按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素 f = open('/Users/kylewhite/Downloads/a.txt', 'r') list1 = f.readlines() # # ['hellod\n', 'world\n'] print(list1)
# readline():一次只读取一行数据 f = open('/Users/kylewhite/Downloads/a.txt', 'r') content = f.readline() print(f'第一行:{content}') content = f.readline() print(f'第二行:{content}')
③ 文件写入
# write() f = open('/Users/kylewhite/Downloads/a.txt', 'w') f.write('hello world')
④ 文件关闭
# close() f = open('/Users/kylewhite/Downloads/a.txt', 'r') f.close()
-
文件移动指针:用来移动文件指针
# seek(偏移量,开始位置) f = open('/Users/kylewhite/Downloads/a.txt', 'r') # 每次读取1M数据 f.seek(1024 * 1024, 0) f.close()
2.2 常用函数(OS模块介绍)
-
os模块介绍
os模块提供了多数操作系统的功能接口函数。当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件、目录打交道,这时就离不了os模块
-
导包
import os
-
获取信息
# 获取当前系统的名字:Windows 返回 'nt'; Linux 返回'posix' os.name # 获取当前工作的目录:get current work directory os.getcwd() # 获取当前目录下的所有文件和文件夹:只获取一层;只有名字 os.listdir('/Users/kylewhite/Downloads') # 获取当前目录下的所有文件和文件夹:只获取一层;绝对路径 os.walk('/Users/kylewhite/Downloads') # 返回路径的目录和文件名 os.path.split('/Users/kylewhite/Downloads/a.txt') # 获得文件的大小,如果为目录,返回0 os.path.getsize() # 获得绝对路径 os.path.abspath() # 连接目录和文件名,与os.path.split(path)相对 os.path.join(path, name) # 返回文件名 os.path.basename(path) # 返回文件路径 os.path.dirname(path)
-
判断
# 判断指定对象是否为文件 os.path.isfile('/Users/kylewhite/Downloads/a.txt') # 判断指定对象是否为目录 os.path.isdir('/Users/kylewhite/Downloads') # 检验指定的对象是否存在 os.path.exists('/Users/kylewhite/Downloads/a.txt')
-
执行
# 删除path指定的文件 os.remove('/Users/kylewhite/Downloads/a.txt') # 删除path指定的目录 os.rmdir('/Users/kylewhite/Downloads') # 创建path指定的目录 os.mkdir('/Users/kylewhite/Downloads') # 执行shell命令:返回值是脚本的退出状态码,0代表成功,1代表不成功 os.system(cmd) # 改变目录到指定目录 os.chdir(path)
2.3 文件备份
-
文件备份
import os file_path = input('请输入你要备份的文件名!') if not os.path.exists(file_path): print('文件路径不存在') dir_name = os.path.dirname(file_path) old_file_name = os.path.basename(file_path) backup_file_path = dir_name + os.sep + old_file_name[:old_file_name.rfind('.')] + '[备份]' + old_file_name[ old_file_name.rfind('.'):] old_file = open(file_path, 'r') backup_file = open(backup_file_path, 'w') while True: content = old_file.read(1024) if len(content) == 0: break backup_file.write(content) old_file.close() backup_file.close()
第三章 递归
3.1 递归介绍
-
递归
递归是一种编程思想
-
递归使用场景
① 文件夹遍历
② 算法
-
递归的特点
① 函数内部自己调用自己
② 必须有出口
3.2 递归深度
-
递归深度
python 解释器为了避免内存溢出和性能影响设置了最大递归深度为998, 当调用栈超过998层就会报错
超过递归深度后,会抛出异常:RecursionError: maximum recursion depth exceeded in comparison
-
设置递归深度
import sys # 设置最大递归深度为3000 sys.setrecursionlimit(3000)
3.3 递归案例
-
累加
求20以内的整数累加
# 累加 def accumulate(num): if num == 0: return 0 return num + accumulate(num - 1) print(accumulate(20))
-
文件夹递归
对指定文件夹路径遍历并将所有文件路径返回列表
def get_all_file(path, files=None): if files is None: files = [] if os.path.isfile(path): files.append(path) return files for file in os.listdir(path): file = os.path.join(path, file) if os.path.isfile(file): files.append(file) else: get_all_file(file, files) return files print(get_all_file('/Users/kylewhite/Downloads'), [])
第四章 Lambda表达式
4.1 Lambda表达式介绍
-
Lambda表达式使用场景
如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化
-
Lambda语法
① lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用
② lambda表达式能接收任何数量的参数但只能返回一个表达式的值
lambda 参数列表 : 表达式
-
简单使用
def fn1(): return 100 print(fn1) # <function fn1 at 0x10092b0d0> print(fn1()) # 100 fn2 = lambda: 200 print(fn2) # <function <lambda> at 0x1009e0c10> print(fn2()) # 200 # 两数相加 fn3 = lambda a, b: a + b print(fn3(10, 20))
4.2 Lambda表达式的参数形式
-
无参数形式
fn1 = lambda: 100 print(fn1())
-
一个参数
fn1 = lambda a: a print(fn1('hello world'))
-
默认参数
fn1 = lambda a, b, c=100: a + b + c print(fn1(10, 20))
-
可变参数:*args
注意:这里的可变参数传入到lambda之后,返回值为元组
fn1 = lambda *args: args print(fn1(10, 20, 30))
-
可变参数:**kwargs
fn1 = lambda **kwargs: kwargs print(fn1(name='python', age=20))
4.3 Lambda的应用
-
带判断的lambda
fn1 = lambda a, b: a if a > b else b print(fn1(1000, 500))
-
列表数据按字典key的值排序
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)