函数
函数就是将⼀段具有独⽴功能的代码块 整合到⼀个整体并命名,在需要的位置调⽤这个名称即可完成对
应的需求。
函数在开发过程中,可以更⾼效的实现代码重⽤
创建:
def 函数名(参数):
代码1
代码2
......
调用:
函数名(参数)
注意:
1. 不同的需求,参数可有可⽆。
2. 在Python中,函数必须先定义后使⽤。
##例子
# 因为函数要先定义再调用,所以步骤2和3要在步骤1的上面书写
# 2. 确定选择功能界面: 显示余额 存款 取款; # 3. 封装函数
def sel_func():
print('显示余额')
print('存款')
print('取款')
# 1. 搭建整体框架
"""
输入密码登录后显示功能; 查询余额后显示功能; 取完钱后显示功能
"""
print('恭喜您登录成功')
# 显示功能界面# 4. 在需要的位置调用函数
sel_func()
print('您的余额是10000000')
# 显示功能界面# 4. 在需要的位置调用函数
sel_func()
print('取了100元钱')
# 显示功能界面# 4. 在需要的位置调用函数
sel_func()
###注意事项
# 1. 使用一个函数 2.测试注意事项
# 需求:一个函数:打印hello world
# info_print() # 报错
# 定义函数
def info_print():
print('hello world')
# 调用函数
info_print()
"""
结论:
1. 函数先定义后调用,如果先调用会报错
2. 如果没有调用函数,函数里面的代码不会执行
3. 函数执行流程***
当调用函数的时候,解释器回到定义函数的地方去执行下方缩进的代码,当这些代码执行完,回到调用函数的地方继续向下执行
定义函数的时候,函数体内部缩进的代码并没有执行
"""
函数参数
# 定义函数
def add_num1():
result = 1 + 2
print(result)
# 调⽤函数
add_num1()
# 1. 函数:固定数据1 和 2 加法
def add_num1():
result = 1 + 2
print(result)
add_num1()
# 2. 参数形式传入真实数据 做加法运算
def add_num2(a, b):
result = a + b
print(result)
add_num2(10, 20)
add_num2(100, 200)
# add_num2(100) # 报错,定义函数有2个参数,传入数据也要是2个
函数的返回值作⽤
# 定义一个函数,返回 烟
def buy():
return '烟'
goods = buy()
print(goods)
# return返回结果给函数调用的地方
"""
return 作用:
1. 负责函数返回值
2. 退出当前函数:导致return下方的所有代码(函数体内部)不执行
"""
说明文档
定义文档
def 函数名(参数):
""" 说明⽂档的位置 """
代码
......
查看文档
help(函数名)
# help(len) # help函数作用:查看函数的说明文档(函数的解释说明的信息)
# def sum_num(a, b):
# """求和函数"""
# return a + b
#
#
# help(sum_num)
# 函数的说明文档的高级使用
def sum_num1(a, b):
"""
求和函数sum_num1
:param a: 参数1
:param b: 参数2
:return: 返回值
"""
return a + b
help(sum_num1)
函数嵌套调⽤
所谓函数嵌套调⽤指的是⼀个函数⾥⾯⼜调⽤了另外⼀个函数。
# 两个函数 testA 和 testB -- 在A里面嵌套调用B
# B函数
def testB():
print('B函数开始-----')
print('这是B函数')
print('B函数结束-----')
# A函数
def testA():
print('A函数开始-----')
# 嵌套调用B
testB()
print('A函数结束-----')
testA()
#如果函数A中,调⽤了另外⼀个函数B,那么先把函数B中的任务都执⾏完毕之后才会回到上次函数A执⾏的位置
变量作用域
变量作⽤域指的是变量⽣效的范围,主要分为两类: 局部变量和全局变量。
局部变量
所谓局部变量是定义在函数体内部的变量,即只在函数体内部⽣效。
局部变量的作⽤:在函数体内部,临时保存数据,即当函数调⽤完成后,则销毁局部变量
全局变量
所谓全局变量,指的是在函数体内、外都能⽣效的变量
# 定义一个函数,声明一个变量:函数体内部访问、函数体外面访问
def testA():
a = 100
print(a) # 函数体内部访问,能访问到a变量
testA()
# print(a) # 报错: a变量是函数内部的变量,函数外部无法访问 -- a是一个局部变量
# 声明全局变量:函数体内外都能访问
a = 100
print(a)
def testA():
print(a)
def testB():
print(a)
testA()
testB()
修改全局变量
# B函数想要a的取值是200
a = 100
print(a)
def testA():
print(a)
def testB():
# a = 200 # 如果直接修改a=200,此时的a是全局a还是局部a? -- 得到结论:这个a是局部变量
# # 因为在全局位置(B函数调用后)打印a得到的不是200而是100
# print(a)
# 想要修改全局变量a,值是200
global a # 声明a为全局变量
a = 200
print(a)
testA()
testB()
print(a)
"""
总结:
1. 如果在函数里面直接把变量a=200赋值,此时的a不是全局变量的修改,而是相当于在函数内部声明了一个新的局部变量
2. 函数体内部修改全局变量: 先global声明a为全局变量,然后再变量重新赋值
"""
多函数程序执⾏流程
⼀般在实际开发过程中,⼀个程序往往由多个函数(后⾯知识中会讲解类)组成,并且多个函数共享某
些数据,
# 1. 声明全局变量;2. 定义两个函数;3. 函数一修改全局变量;函数2访问全局变量
glo_num = 0
def test1():
global glo_num
glo_num = 100
def test2():
print(glo_num)
print(glo_num) # 0, 因为修改的函数没执行
test2() # 0 , 因为修改的函数没执行
test1()
test2() # 100,先调用了函数1
print(glo_num) # 100 , 调用了函数1
######## 函数返回值作为参数传递
# 1. 定义两个函数;2. 函数一有返回值50;函数二把返回值50作为参数传入(定义函数二要有形参)
def test1():
return 50
def test2(num):
print(num)
# 先得到函数一的返回值,再把这个返回值传入到函数二
result = test1()
# print(result)
test2(result)
函数的返回值
- return a, b 写法,返回多个数据的时候,默认是元组类型。
- return后⾯可以连接列表、元组或字典,以返回多个值。
# 需求:一个函数有两个返回值1和2
# 一个函数如果有多个return不能都执行,只执行第一个return:无法做法一个函数多个返回值
# def return_num():
# return 1
# return 2
#
#
# result = return_num()
# print(result)
# 一个函数多个返回值的写法
def return_num():
# return 1, 2 # 返回的是元组
# return后面可以直接书写 元组 列表 字典,返回多个值
# return (10, 20)
# return [100, 200]
return {'name': 'Python', 'age': 30}
result = return_num()
print(result)
函数的参数
位置参数 :调⽤函数时根据函数定义的参数位置来传递参数。
# 需求:函数3个参数name,age,gender
def user_info(name, age, gender):
print(f'您的姓名是{name}, 年龄是{age}, 性别是{gender}')
# user_info('TOM', 20, '男')
# user_info('TOM', 20) # 个数定义和传入不一致会报错
user_info(20, 'TOM', '男') # 顺序也和定义必须是一致的,否则导致数据无意义
#注意:传递和定义参数的顺序及个数必须⼀致
关键字参数
函数调⽤,通过“键=值”形式加以指定。可以让函数更加清晰、容易使⽤,同时也清除了参数的顺序需
求。
def user_info(name, age, gender):
print(f'您的姓名是{name}, 年龄是{age}, 性别是{gender}')
# 调用函数传参
user_info('ROSE', age=20, gender='女')
user_info('小明', gender='男', age=18) # 关键字参数之间不分先后顺序
# 位置参数必须写在关键字参数的前面
# user_info(age=20, gender='男', 'TOM')
缺省参数
缺省参数也叫默认参数,⽤于定义函数,为参数提供默认值,调⽤函数时可不传该默认参数的值(注
意:所有位置参数必须出现在默认参数前,包括函数定义和调⽤)
def user_info(name, age, gender='男'):
print(f'您的姓名是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 18) # 没有为缺省参数传值,表示使用默认值
user_info('TOM', 18, gender='女') # 为缺省参数传值,使用这个值,即修改了默认值
#函数调⽤时,如果为缺省参数传值则修改默认参数值;否则使⽤这个默认值
不定⻓参数
不定⻓参数也叫可变参数。⽤于不确定调⽤的时候会传递多少个参数(不传参也可以)的场景。此时,可
⽤包裹(packing)位置参数,或者包裹关键字参数,来进⾏参数传递,会显得⾮常⽅便。
#位置参数
# 接收所有位置参数,返回一个元组
def user_info(*args):
print(args)
user_info('TOM')
user_info('TOM', 20)
user_info('TOM', 20, 'man')
user_info()
#传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为⼀个元组(tuple),
args是元组类型,这就是包裹位置传递。
#
# 收集所有关键字参数,返回一个字典
def user_info(**kwargs):
print(kwargs)
user_info()
user_info(name='TOM')
user_info(name='TOM', age=20)
###⽆论是包裹位置传递还是包裹关键字传递,都是⼀个组包的过程。
拆包和交换变量值
# 1. 拆包元组数据
# def return_num():
# return 100, 200
#
#
# # result = return_num()
# # print(result)
# num1, num2 = return_num()
# print(num1)
# print(num2)
# 2. 字典数据拆包: 变量存储的数据是key值
# 先准备字典,然后拆包
dict1 = {'name': 'TOM', 'age': 20}
# dict1中有两个键值对,拆包的时候用两个变量接收数据
a, b = dict1
print(a)
print(b)
# v值
print(dict1[a])
print(dict1[b])
交换变量值
# a = 10
# b = 20
# 1. 方法一
"""
1.1 定义中间的第三变量,为了临时存储a或b的数据
1.2 把a的数据存储到c,做保存
1.3 把b的数据赋值到a, a = 20
1.4 把c的数据赋值到b, b = 10
"""
# c = 0
# c = a
# a = b
# b = c
#
# print(a)
# print(b)
a, b = 1, 2
print(a)
print(b)
a, b = b, a
print(a)
print(b)
引用
# 可变和不可变
# 1. 不可变:int: 1.1 声明变量保存整型数据,把这个数据赋值到另一个变量; id()检测两个变量的id值(内存的十进制值)
# a = 1
# b = a
#
# print(b)
#
# # 发现a和b的id值相同的
# print(id(a))
# print(id(b))
#
# # 修改a的数据测试id值
# a = 2
#
# print(b)
#
# # 因为修改了a的数据,内存要开辟另外一份内存取存储2,id检测a和b的地址不同
# print(id(a))
# print(id(b))
# 2. 可变类型:列表
aa = [10, 20]
bb = aa
print(bb)
print(id(aa))
print(id(bb))
aa.append(30)
print(aa)
print(bb) # 列表是可变类型
print(id(aa))
print(id(bb))
# 需求:引用是否可以当做实参
"""
1. 定义函数: 有形参
1.1 访问打印形参看是否有数据
1.2 访问形参的id
1.3 改变形参的数据,查看这个形参并打印id,看id值是否相同
2. 调用函数 -- 把可变和不可变两种类型依次当做实参传入
"""
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
b = 100
test1(b)
c = [11, 22]
test1(c)
可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进⾏修改,如果能直接修改那么就是可变,否则是不可
变.
可变类型
列表
字典
集合
不可变类型
整型
浮点型
字符串
元组
递归
特点
函数内部⾃⼰调⽤⾃⼰
必须有出⼝
# 例子
# 需求:3以内数字累加和 3 + 2 + 1 = 6
# 6 = 3 + 2以内数字累加和
# 2以内数字累加和 = 2 + 1以内数字累加和
# 1以内数字累加和 = 1 # 出口
# 递归特点:函数内部自己调用自己;必须有出口
def sum_numbers(num):
# 2. 出口
if num == 1:
return 1
# 1. 当前数字 + 当前数字-1的累加和
return num + sum_numbers(num-1)
result = sum_numbers(3)
print(result)
# 如果没有出口,报错:超出最大递归深度
lambda 表达式
lambda 参数列表 : 表达式
注意
lambda表达式的参数可有可⽆,函数的参数在lambda表达式中完全适
lambda表达式能接收任何数量的参数但只能返回⼀个表达式的值。
# 需求:函数 返回值100
# 1. 函数
# def fn1():
# return 100
#
# result = fn1()
# print(result)
# 2. lambda 匿名函数
# lambda 参数列表: 表达式
fn2 = lambda: 100
print(fn2) # lambda内存地址
# 100返回值 调用函数
print(fn2())
#lambda表达式
# 1. 无参数
# fn1 = lambda: 100
# print(fn1())
# 2. 一个参数
# fn2 = lambda a: a
# print(fn2('hello world'))
# 3. 默认参数/缺省参数
# fn3 = lambda a, b, c=100: a + b + c
# print(fn3(10, 20))
# print(fn3(10, 20, 200))
# 4. 可变参数:*args
# fn4 = lambda *args: args
# print(fn4(10, 20))
# print(fn4(10, 20, 30, 40))
# print(fn4(10)) #返回元组
# 5. 可变参数:**kwargs
fn5 = lambda **kwargs: kwargs
print(fn5(name='Python'))
print(fn5(name='Python', age=30)) #返回字典
#列表排序使用lambda表达式
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]
# sort(key=lambda..., reverse=bool数据)
# 1. name key对应的值进行升序排序
students.sort(key=lambda x: x['name'])
print(students)
# 2. name key对应的值进行降序排序
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 3. age key对应的值进行升序排序
students.sort(key=lambda x: x['age'])
print(students)
⾼阶函数
# abs(): 绝对值
# print(abs(-10))
# round(): 四舍五入
print(round(1.2))
print(round(1.9))
# 1. 写法一
# def add_num(a, b):
# # 绝对值
# return abs(a) + abs(b)
#
#
# result = add_num(-1.1, 1.9)
# print(result)
# 2. 写法二:高阶函数:f是第三个参数,用来接收将来传入的函数
def sum_num(a, b, f):
return f(a) + f(b)
result1 = sum_num(-1, 5, abs)
print(result1)
result2 = sum_num(1.1, 1.3, round)
print(result2)
#map函数:map(func, lst),将传⼊的函数变量func作⽤到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
# 1. 准备列表数据
list1 = [1, 2, 3, 4, 5]
# 2. 准备2次方计算的函数
def func(x):
return x ** 2
# 3. 调用map
result = map(func, list1)
# 4. 验收成果
print(result)
print(list(result))
#reduce函数:reduce(func, lst),其中func必须有两个参数。每次func计算的结果继续和序列的下⼀个元素做累积计算。
#注意: reduce()传⼊的参数func必须接收2个参数
list1 = [1, 2, 3, 4, 5]
# 1. 导入模块
import functools
# 2. 定义功能函数
def func(a, b):
return a + b
# 3. 调用reduce,作用:功能函数计算的结果和序列的下一个数据做累计计算
result = functools.reduce(func, list1)
print(result)
#filter函数:过滤符合条件的元素
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 1. 定义功能函数:过滤序列中的偶数
def func(x):
return x % 2 == 0
# 2. 调用filter
result = filter(func, list1)
print(result)
print(list(result))