一、函数
1.1 函数定义
函数定义:实现特定功能的代码块
函数的作用:
- 简化代码
- 提高代码重用性
- 便于维护和修改
- 可提高代码的可拓展性
函数三要素:功能、参数、返回值
函数定义的语法格式:
函数分类:
从定义的角度——内置函数 自定义函数
从参数的角度——无参函数 有参函数
从返回值的角度——无返函数None 有返函数
函数名就是函数的地址
def fun():print("hello world")
print(fun)#<function fun at 0x0000021D9FC8A2A0>有参无返函数
def fun(num):print(num)
fun(5)#5有参有返函数
def fun(num):return num
print(fun(5))#5
1.2 函数的参数传递
位置参数
位置参数:调用函数时根据函数定义的位置来传递参数
def user_into(name , age , gender):print(f'您的名字是{name},年龄是{age},性别是{gender}')user_into('tom',18,'男')#您的名字是tom,年龄是18,性别是男
注意:传递参数和定义参数的顺序和个数必须一致
关键字参数
关键字参数:函数调用时通过“键 = 值”形式传递参数
作用:可以让函数更加的清晰,容易使用,同时也清除了参数的顺序需求
def user_info(name , age , gender):print(f'您的名字是{name},年龄是{age},性别是{gender}')# 关键字传参
user_info(name = "小明",age = 18,gender = "男")
# 可以不按照固定顺序传参
user_info(age = 18,gender='男',name = '小李')
# 可以位置和参数进行混用,位置参数必须在前,且匹配参数顺序
user_info("小苑",age = 20,gender = "女")
注意:函数调用时,如果有参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
缺省参数
缺省参数:缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值
def user_info(name , age , gender = "男"):print(f'您的名字是{name},年龄是{age},性别是{gender}')user_info('jack',age = 18) #您的名字是jack,年龄是18,性别是男
user_info('rose',18,'女') #您的名字是rose,年龄是18,性别是女
注意:函数调用时,如果为缺省参数传递值则修改默认参数值,否则使用这个默认值
不定长参数
不定长参数:不定长参数也叫可变参数,用于不确定 调用的时候会传递多少个参数(不传参也可以)的场景。
作用:当调用函数时不确定参数的个数时,可以使用不定长参数
不定长参数的类型:
1、位置传递
2、关键字传递
位置传递
def user_info(*args):print(args)user_info('tom') #tom
user_info('tom',18) #tom,18当多条输入时候避免输入值都存入args中,要进行关键字传值
def user_info2(*args, a, b):print(args,a,b)
user_info2(1,2,3,4,a=5,b=6)#(1, 2, 3, 4) 5 6当其他输入在前,只考虑位置就行
def user_info2(a, b,*args):print(args,a,b)
user_info2(1,2,3,4,5,6)#(3, 4, 5, 6) 1 2
注意:它会根据传进的参数的位置合并为一个元组(tuple),args是元组的类型,这就是位置传递
关键字传递
向函数内传递的时候要按照 key = value 的形式传递
def user_info(**kwargs):print(kwargs)user_info(name = 'tom',age = 18,id = 110)
#{'name': 'tom', 'age': 18, 'id': 110} 是一个键值对 字典的形式
注意:参数是”键 = 值“ 形式的情况下,所有的”键 = 值“ 都会被kwargs接受,同时会根据 “键 = 值” 组成字典
习题:定义函数,参数为关键字可变长参数,请将其中HuaHua的身高修改为160, 然后打印出所有身高不足180的姓名, 使用fun(XiaoMing=155,XiaoHong=171,XiaoHei=192,HuaHua=2333)调用测试
def fun(**num):if 'HuaHua' in num: num['HuaHua'] = 160for i in num.keys():if num[i]<180:print(i,end = ' ')
fun(XiaoMing=155,XiaoHong=171,XiaoHei=192,HuaHua=2333)#XiaoMing XiaoHong HuaHua
形参:函数定义时的参数,没有实际意义
- def fun(a)
- def fun(a:int)
- def fun(*a)
- def fun(**a)
实参:函数调用/使用时的参数,有实际意义
- fun(1, 'a', 13.14, True, [1,2], (3,4), {1,2})
- fun( len(s) )
1.3 函数的返回值
- 如果函数的运行结果想在函数外使用,就需要设置返回值。
- 使用关键字 return 进行返回。
- return 可以在函数中出现多次,但是只执行 1 次,遇见return返回值并结束函数。
- 与C语言不同,python中的return可以返回一个值或多个值,用逗号隔开这个时候将返回的多个值到打包成一个元组。
#求输入的列表的最大值和最小值
def fun(num):return max(num),min(num)
print(fun([1,2,3,4,5,6]),type(fun([1,2,3,4,5,6])))
#(6, 1) <class 'tuple'>
练习题:定义函数,参数为关键字可变长参数,请计算并返回他们的平均身高, 使用(xiaoming='178cm',xiaobai='182cm',xiaohong='166cm',xiaohei='174cm')
#利用切片
def fun(**kwargs):sum = 0for i in kwargs.values():sum+=int(i.split('cm')[0])#利用字符串替换函数(replace)sum+=int(i.replace("cm",""))return sum/len(kwargs)
print(fun(xiaoming='178cm',xiaobai='182cm',xiaohong='166cm',xiaohei='174cm'))#175.0
1.4 递归函数
函数调用方式:
- 直接调用 A调用A
- 间接调用 B调用B
递归的思想:把一个大规模问题分解成相似的小规模问题,再将小规模问题分解成相似的小小规模问题……。
#递归求前n项和
def fun(n):if n ==0:return 0else:return fun(n-1)+n
n = int(input(">>"))
print(fun(n))#利用循环求前n项和
n = int(input(">>"))
sum=0
for i in range(n+1):sum+=i
print(sum)
对比发现:循环和递归很相似,基本上他们两个可以相互转换。
- 大多数情况下,循环的效率、性能更好一些
- 循环代码容易书写,阅读性差
- 递归代码写起来稍难,阅读性好
递归函数有三要素:
- 边界条件/基线条件 跳出/结束递归的条件
- 递归返回段 满足结束条件时,返回
- 递归前进段 不满足结束条件时,前进/继续递归
1.5 函数中变量的作用域
变量的作用域:是指变量能起作用的范围,根据作用范围大小不同分为全局变量和局部变量。
- 全局变量:定义在函数外,作用范围是整个程序,程序结束时全局变量声明周期结束。
- 局部变量:定义在函数代码块里或者函数的参数里,作用范围是整个函数,函数执行结束时局部变量生命周期结束。
# 全局变量作用域全局
a = 10
def fun1():print(a)
def fun2():print(a)fun1()#10
fun1()#10# 局部变量不能被外部调用作用域只能在直接函数体内
def fun3():a = 20print(a) #可以与全局变量重名但局部变量会覆盖全局变量【就近原则】
# def fun4():
# print(a)
fun3()#20
# fun4()#error
1.6 函数嵌套
函数嵌套:在一个函数的内部 还嵌套定义了 另外一个函数。
外部的我们称之为 外函数,内部的我们称之为 内函数。
#无返回值
def out_func():print('欢迎',end='')def in_func():print('光临')in_func()
out_func()#欢迎光临#内函数有返回值
def out_func():print('欢迎',end='')def in_func():print('光临')return in_func()
out_func()#欢迎光临
1.7 global 和 nonlocal的区别
x = 200
def out_func():def in_func():global xx = 100print('内函数',x)in_func()print('外函数',x)
out_func()
"""
global会把函数里的局部变量变成全局变量
内函数 100
外函数 100
"""def out_func():x = 666def in_func():nonlocal xx = 888print('内函数',x)in_func()print('外函数',x)
out_func()
"""
nonlocal只能修饰上一层的局部变量
内函数 888
外函数 888
"""
内函数局部变量 > 外函数局部变量 > 全局变量
对比global 和 nonlocal:
① global 修饰全局变量
② nonlocal 修饰该函数上一层的局部变量
1.8 闭包函数
什么是闭包函数?——如果内函数中使用了外函数的局部变量,并且外函数把内函数返回的过程就叫闭包。
形成闭包的条件:
- 函数嵌套
- 将内函数作为返回值返回
- 内函数要使用外函数的局部变量
#利用闭包计算两个数相乘
def out_fun(n1):def in_fun(n2):return n1*n2return in_fun
print(out_fun(4)(5))#20#也可以定义一个变量来接收out_fun()返回的in_out()的地址
def out_fun(n1):def in_fun(n2):return n1*n2return in_fun
result = out_fun(5)
print(result(4))#20