1、函数目的
函数又称方法,其主要为封装一系列代码,减少代码的重复编写,提高代码的复用
2、函数定义(声明)
函数使用关键字def声明,下列函数中hello为函数名,后跟():,函数中语句块缩进四个字符
def hello():
print("Hello World!")
3、函数调用
函数的调用直接使用函数名(),进行调用。
hello()
结果如下:
4、函数形参、函数实参
形参是在函数定义时()中的变量,下列实例exchange(x,y)中的x,y就是形参
def exchange(x, y):
"""
交换函数
:param x: 形参x
:param y: 形参y
:return: 返回值交换后的x,y
"""
temp = x
x = y
y = temp
# return函数执行结束,后续代码不在执行
return x, y
实参就是在函数调用是()中放的值,下列实例中的10,20就是实参
print(exchange(10, 20))
函数返回多个值默认以元组的形式返回
实参的位置可以填写有确切值的变量
a = 10
b = 20
print(exchange(a, b), type(exchange(a, b)))
结果如下
5、函数返回值
函数使用return返回结果,默认为None。如果函数中有print()函数则每调用一次函数,print()就会执行一次。
def hello():
print("Hello World!")
print(hello())
结果如下
6、函数的参数类型
位置参数可以有多个,但在调用时实参个数不能少于位置参数的个数,实参中传入多余的位置参数
全部放入元组参数中,在函数定义时定义默认值的参数,可在实参中通过关键字修改默认值。实参中使用没有默认值的关键字参数会传入关键字参数。
def multi(n, *args, title="学习", address="学校", **kwargs):
"""
函数参数测试函数
:param n: 位置参数
:param args: 可变元组参数
:param title: 默认函数
:param address: 默认函数
:param kwargs: 字典参数
"""
print(f"n:{n}")
for arg in args:
print(f"args:{args}")
print(f"title:{title}")
print(f"address:{address}")
print(f"kwargs:{kwargs}")
multi(3, 6, 9, 12, title="工作", address="公司", travel="bike", info="hello world")
结果如下
7、变量的作用域(global与nonlocal)
在程序开始时就定义好的变量,称为全局变量,声明的函数内部可以查看全局变量。声明在函数内部的变量为局部变量,只能在函数内部使用。
1.global
a = 10
print(a)
data = [1, 2, 3]
def my_fun():
# global声明a为全局变量a,不使用global声明不可以修改全局变量,只能查看
"""
# 函数执行时先开辟内存给局部变量,
# 未使用global声明变量a,函数会默认打印局部变量a = 20,
# 因为局部变量a的使用出现在定义前,所以程序会报错
print(a)
a = 20
"""
global a
print(a)
a = 20
print(a)
"""
在函数中可以使用data.append(),因为data是可变类型,data指向列表,本质是列表自身变化
而data = [10, 20],是将新的列表赋值给data,改变的是变量data的指向。
"""
my_fun()
print(a)
2.nonlocal
# nonlocal 在函数嵌套时,内部函数更改外部函数的值,需要先用nonlocal声明变量。
a = 1000
def fun1():
a = 10
def fun2():
nonlocal a
a = 20
print(1, a)
print(a)
fun2()
print(2, a)
return fun2
print(3, a)
fun1()
r = fun1()
r()
8、递归函数
递归函数的特点:自己调用自己,必须设置一个递归出口结束递归
def my_sum(n):
if n == 1:
return 1
else:
return n + my_sum(n - 1)
print(my_sum(5))
9、匿名函数
使用关键字lambda声明,没有名字,一般在函数调用时将匿名函数传给函数的形参变量。
# 可以没有参数
# my_fun = lambda: print("hello")
#
# my_fun()
# 可以有多个参数
# my_fun = lambda a, b: print(a,b)
#
# my_fun(10, 20)
# 可以写三元表达式
# my_fun = lambda a, b: a if a > b else b
#
# print(my_fun(100, 200))
案例:
datas = [
{
"id": 101,
"name": "张三",
"age": 25,
"sex": "男"
},
{
"id": 102,
"name": "李四",
"age": 35,
"sex": "男"
}
]
def my_max(items, f):
max_age = 0
max_e = None
for item in items:
if f(item) > max_age:
max_age = f(item)
max_e = item
print(max_e)
# 匿名函数返回传入字典age的值
my_max(datas, lambda e: e["age"])
字典不能直接和字典比较,上述案例是用字典中的键age对应的值比较,返回age最大的字典。
10、闭包
# 闭包的工作原理是,内部函数不仅保存了其自身的执行环境,
# 还保留了对外部函数中定义的变量的引用。当外部函数返回内部函数时,
# 这个内部函数就形成了一个闭包,它能够访问外部函数的局部变量
# def fun1():
# dates = []
# def fun2():
# dates.append("hello")
# print(dates)
# return fun2
# fun1()返回fan2()的函数名
# print(fun1())
#
# r = fun1()
# r()等同于调用fun2()
# r()
#
# r = fun1()
# # r指向的地址fun2()方法中保存有自己的列表
# r()
# r()
#
# # 与r的列表不相干
# r1 = fun1()
# r1()
# r1()
# global 表明在函数内部使用的a是全局变量a