Python基础教程(六):函数+练习题
一、函数的定义
1. 函数的定义:实现【特定功能】的代码块。
2. 函数的作用:
a、简化代码
b、提高代码重用性
c、便于维护和修改
d、提高代码的可扩展性
3. 函数的三要素:
功能 |
len(),max(),sum() |
参数 | list.clear(),list.append(‘hello') |
返回值 | list.sort(),nlist = sorted(list) |
4. 函数定义的语法格式:
def max(a, b):
if a > b:
return a
else:
return b
# 函数可以输入参数,并设置返回值
# 使用 def 关键字定义函数
# a、b为函数参数
# return 关键字设置返回值
5. 函数的分类
a、从定义角度:内置函数(别人写好的,可直接用);自定义函数;
b、从参数角度:无参函数;有参函数;
c、从返回值角度:无返函数None;有返函数;
6. 函数的调用/使用
a. 无返函数:函数名()
b. 有返函数:
方法1:print(函数名())
def my_fun():
print("这是我的函数。")
print(my_fun)
# 【输出结果】:<function my_fun at 0x1008b72e0>,说明函数名是一个内存地址
my_fun() # 无返函数直接调用
# 【输出结果】:这是我的函数。
方法2:变量名 = 函数名()
def num_fun():
return 100
print(num_fun()) # 有返函数,输出调用
ret = num_fun() # 有返函数,使用变量接收调用
print(ret)
#【运行结果】:
# 100
# 100
二、函数的参数传递
2.1: 形参和实参
形参:函数定义时的参数,没有实际意义
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))
2.2:函数在进行参数传递的时候,分为:
位置参数、关键字参数、默认参数、位置不定长参数、关键字不定长参数。
a. 位置参数:
传递参数时应该和“定义时的参数”保持位置和数量一一对应。
# 【示例】位置参数
def fun(a, b, c):
print(a, b, c)
fun(1, 2, 3)
#【运行结果】:
# 1 2 3
b. 关键字参数:
调用函数传递参数时,按照“参数名=值”的方式;
传参的顺序可以和定义参数的顺序不一致。
# 【示例】关键字参数
def fun(name, age, sex):
print(name, age, sex)
fun(name='张三', age=18, sex='男')
fun(age=18, sex='男', name='张三')
#【运行结果】:
# 张三 18 男
# 张三 18 男
c. 默认参数:
在函数定义时,给参数设置默认值;
则函数调用时,若不传参就是用默认值,若传参就是用传参的值。
# 【示例】默认参数
def fun(name='张三', age=18, sex='男'):
print(name, age, sex)
fun()
fun('李四')
fun(age=66)
fun('小明', 30)
fun('小华', 23, '女')
#【运行结果】:
# 张三 18 男
# 李四 18 男
# 张三 66 男
# 小明 30 男
# 小华 23 女
d. 位置不定长参数:
在定义函数时参数名前加 * ,也就是def fun( *args );
在传参的时候就可以传若干个位置参数,并将参数打包成“元组”。
# 【示例】位置不定长参数
# 问:在一个函数中,位置不定长参数,可以有两个吗?
# 答:不允许
# 问:一旦定义了位置不定长参数,是不是就不可以定义其他参数了呢?
# 答:可以定义其他参数,但是传参时必须是关键字参数
def test1(*num):
print(num)
test1(1)
test1(1, 2)
test1(1, 2, 3, 4, 5, 6)
#【运行结果】:
# (1,)
# (1, 2)
# (1, 2, 3, 4, 5, 6)
def test2(*num, a, b):
print(num)
print(a)
print(b)
test2(1, 2, 3, 4, a=5, b=6)
#【运行结果】:
# (1, 2, 3, 4)
# 5
# 6
def test3(a, b, *num):
print(a)
print(b)
print(num)
test3(1, 2, 3, 4, 5, 6, 7)
#【运行结果】:
# 1
# 2
# (3, 4, 5, 6, 7)
def test4(a, *num, b):
print(a)
print(num)
print(b)
test4(1, 2, 3, 4, 5, b=66)
#【运行结果】:
# 1
# (2, 3, 4, 5)
# 66
e. 关键字不定长参数:
在定义函数参数名前加 ** ,也就是 def fun( **kwargs );
在传参的时候就可以传若干个关键字参数,并将参数打包成“字典”。
# 【示例】关键字不定长参数
def fun(**kwargs):
print(kwargs)
fun(a=12, b=13, c=15)
fun(姓名='张三', 年龄=18, 性别='男')
#【运行结果】:
# {'a': 12, 'b': 13, 'c': 15}
# {'姓名': '张三', '年龄': 18, '性别': '男'}
2.3:小练习
# 定义函数,参数为位置可变长参数;
# 请将传入的所有实参,按照升序输出;
def up(*num):
print(sorted(num))
up(2, 5, 8, 1, 4, 9, 7, 15, 12)
# 【运行结果】:
# [1, 2, 4, 5, 7, 8, 9, 12, 15]
# 定义函数,参数为关键字可变长参数,请将其中HuaHua的身高修改为160;
# 打印出所有身高不足180的学生姓名;
# 使用fun(XiaoMing=155, XiaoHong=171, XiaoHei=192, HuaHua=2333)调用测试;
def fun(**students):
if 'HuaHua' in students:
students['HuaHua'] = 160
print(students)
for name in students.keys():
if students[name] < 180:
print(name)
fun(XiaoMing=155, XiaoHong=171, XiaoHei=192, HuaHua=2333)
#【运行结果】:
# {'XiaoMing': 155, 'XiaoHong': 171, 'XiaoHei': 192, 'HuaHua': 160}
# XiaoMing
# XiaoHong
# HuaHua
三、函数的返回值
1、如果函数的运行结果想在函数外使用,就需要设置返回值。
2、使用关键字 return 进行返回。
3、return 可以在函数中出现多次,但是只执行 1 次,遇见 return 返回值并结束函数。
4、Python中的 return 可以返回一个值或多个值,将返回的多个值打包成一个元组。
def fun(*num):
my_sum = 0
for i in num:
my_sum += i
return my_sum
ret = fun(3, 7, 2, 9, 8)
print(ret)
print(type(ret))
#【运行结果】:
# 29
# <class 'int'>
def fun1(*num):
my_sum = 0
even_sum = 0
odd_sum = 0
for i in num:
my_sum += i
if i%2==0:
even_sum += i
else:
odd_sum += i
return my_sum, even_sum, odd_sum
res = fun1(2, 8, 7, 3, 11, 10)
print(res)
print(type(res))
a, b, c = fun1(2, 8, 7, 3, 11, 10)
print(a, b, c)
#【运行结果】:
# (41, 20, 21)
# <class 'tuple'>
# 41 20 21
3.1:简单函数小练习
# 1、定义函数,无参无返,可求出200以内所有包含7的数字;
def num():
num_list = []
list_7 = []
for i in range(200):
num_list.append(str(i))
for j in num_list:
if "7" in j:
list_7.append(j)
print(list_7)
num()
#【运行结果】:
# ['7', '17', '27', '37', '47', '57', '67', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '87', '97', '107', '117', '127', '137', '147', '157', '167', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '187', '197']
# 2、定义函数,无参有返,可返回200-300所有偶数组成的数列;
def num_2():
list_23 = []
for i in range(200, 300+1):
if i % 2 == 0:
list_23.append(i)
print(list_23)
num_2()
#【运行结果】:
# [200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300]
# 3、定义函数,有参无返,可接收任意一个字符串,并计算该字符串有几个字符;
def num_3(s):
print(f"你输入的字符串总计 {len(s)} 个字符。")
len_str = input("请输入一个字符串:")
num_3(len_str)
#【运行结果】:
# 请输入一个字符串:abcdefghijklmnopqrstuvwxyz
# 你输入的字符串总计 26 个字符。
# 4、定义函数,有参有返,可接收任意一个字符串,对其进行去重,返回去重后的集合;
def set_str(s):
set_s = set(s)
print(set_s)
st = input("请输入一个字符串:")
set_str(st)
#【运行结果】:
# 请输入一个字符串:hello world i am adrian!
# {' ', 'e', 'n', 'm', 'r', 'i', 'h', 'l', 'd', '!', 'w', 'a', 'o'}
# 5、定义函数,可接收个数字列表,并返回其中的最大和最小值;
def fun6(l):
max_i = l[0]
min_i = l[0]
for i in l:
if max_i < i:
max_i = i
if min_i > i:
min_i = i
return max_i, min_i
list_6 = [8, 5, 9, 74, 23, 15, 1, 3, 6]
ls_max, ls_min = fun6(list_6)
print(f"最大值为:{ls_max}")
print(f"最小值为:{ls_min}")
#【运行结果】:
# 最大值为:74
# 最小值为:1
# 6、定义函数,参数为关键字可变长参数,请计算他们的平均身高,
# 测试数据:(xiaoming=’178cm’,xiaobai=’182cm’,xiaohong=’166cm’,xiaohei=’174cm’)
def fun_11(**students):
sum_h = 0
sn = 0
for i in students.values():
sum_h += int(i.split('cm')[0])
sn += 1
return sum_h / sn
ret = fun_11(xiaoming='178cm',xiaobai='182cm',xiaohong='166cm',xiaohei='174cm')
print(f"平均身高为:{ret} cm")
#【运行结果】:
# 平均身高为:175.0 cm
四、递归函数
4.1:递归函数:就是自己调用自己的函数。
4.2:递归的思想:把一个大规模问题分解成相似的小规模问题;
再将小规模问题分解成相似的小小规模问题。。。
# 要求定义一个函数,实现输出n遍"我爱python"
def fun(n:int):
while True:
print("我爱python")
n -= 1
if(n==0):
break
fun(10)
# #【运行结果】:
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# # 我爱python
# 要求定义一个递归函数,实现输出n遍"我爱python"
def rec(n:int):
if n==0:
return
else:
print(f"{n} 我爱python")
rec(n-1)
rec(10)
#【运行结果】:
# 10 我爱python
# 9 我爱python
# 8 我爱python
# 7 我爱python
# 6 我爱python
# 5 我爱python
# 4 我爱python
# 3 我爱python
# 2 我爱python
# 1 我爱python
对比发现:“循环”和“递归”很相似,基本上他们两个可以相互转换。
1、大多数情况下,循环的效率、性能更好一些;
2、循环代码容易书写,阅读性差;
3、递归代码写起来稍难,阅读性好。
4.3:递归函数有三要素:
边界条件 / 基线条件 |
跳出 / 结束 递归的条件 |
递归返回段 |
满足结束条件时,返回 |
递归返回段 |
不满足结束条件时,前进 / 继续递归 |
4.4:小练习
# 定义一个递归函数,求n的阶乘;
# 阶乘:就是累乘,从1累乘到本身,或者从本身累乘到1;
# 比如:5! = 1*2*3*4*5 = 5*4*3*2*1
def rec(n):
if n==1:
return 1
else:
return n * rec(n-1)
n = 5
print(f"5!=1*2*3*4*5={rec(n)}")
#【运行结果】:
# 5!=1*2*3*4*5= 120
五、函数中变量的作用域
变量的作用域:是指变量能起作用的范围;
根据作用范围大小不同,分为“全局变量”和“局部变量”。
5.1:全局变量:定义在函数外,作用范围是整个程序;
程序结束时,全局变量声明周期结束。
# 全局变量都能用
quanju = 10
def fun1():
print(quanju)
def fun2():
print(quanju)
print(quanju)
fun1()
fun2()
#【运行结果】:
# 10
# 10
# 10
5.2:局部变量:定义在函数代码块里或者函数的参数里;
作用范围是整个函数,函数执行结束时局部变量生命周期结束。
# 局部变量只能在该函数内使用
def fun1():
a = 10
print(a)
def fun2():
print(f"fun1函数中的{a}")
fun1()
#【运行结果】:
# 10
fun2()
#【运行结果】:
# print(f"fun1函数中的{a}") 报错!
# NameError: name 'a' is not defined
5.3:global关键字的使用
# 若想在函数外,使用该函数的局部变量;
# 使用 global 关键字将该变量修饰为全局变量。
def fun1():
global a
a = 10
print(a)
def fun2():
print(f"fun1函数中的:{a}")
fun1()
fun2()
print(f"fun1函数中的:{a}")
#【运行结果】:
# 10
# fun1函数中的:10
# fun1函数中的:10
5.4:局部变量与全局变量的重名
# 从以下代码可以看到,局部变量可以和全局变量重名;
# 但是:局部变量覆盖全局变量(遵循就近原则);
a = 100 #全局变量
def fun():
a = 200 # 局部变量
print(a)
print(a)
fun()
#【运行结果】:
# 100
# 200
六、函数嵌套
函数嵌套:在一个函数的内部,还嵌套定义了另外一个函数。
外部的我们称之为“外函数”,内部的我们称之为“内函数”。
def out_fun():
print("外函数")
def in_fun():
print("内函数")
in_fun()
out_fun()
#【运行结果】:
# 外函数
# 内函数
def out_fun():
print("外函数")
def in_fun():
print("内函数")
return in_fun()
out_fun()
# #【运行结果】:
# 外函数
# 内函数
def out_fun():
print("外函数")
def in_fun():
print("内函数")
return in_fun
out_fun()()
#【运行结果】:
# 外函数
# 内函数
6.1:global 和 nonlocal
def out_fun():
def in_fun():
global x
x = 100
print(f"内函数里面的{x}")
in_fun()
print(f"这是外函数,想使用内函数里的{x}")
out_fun()
#【运行结果】:
# 内函数里面的100
# 这是外函数,想使用内函数里的100
def out_fun():
x = 666
def in_fun():
nonlocal x
x = 100
print(f"内函数里面的{x}")
in_fun()
print(f"这是外函数,想使用内函数里的{x}")
out_fun()
#【运行结果】:
# 内函数里面的100
# 这是外函数,想使用内函数里的100
6.2:函数嵌套例子对比
x = 100
def out_fun():
# global x
x = 200
def in_fun():
# global x
x = 300
print(f"内函数中输出{x}")
in_fun()
print(f"外函数中输出{x}")
out_fun()
print(f"函数外输出{x}")
#【运行结果】:
# 内函数中输出300
# 外函数中输出200
# 函数外输出100
x = 100
def out_fun():
global x
x = 200
def in_fun():
global x
x = 300
print(f"内函数中输出{x}")
in_fun()
print(f"外函数中输出{x}")
out_fun()
print(f"函数外输出{x}")
#【运行结果】:
# 内函数中输出300
# 外函数中输出300
# 函数外输出300
通过上面的例子可以发现:内函数局部变量 > 外函数局部变量 > 全局变量
对比 global 和 nonlocal:
1. global 修饰全局变量;
2. nonlocal 修饰该函数上一层的局部变量;
七、闭包函数
7.1:什么是闭包?
如果内函数中使用了外函数的局部变量,并且外函数把内函数返回的过程就叫闭包。
形成闭包的条件:
1. 函数嵌套
2. 将内函数作为返回值返回
3. 内函数必须使用外函数的局部变量
7.2:示例代码
# out_fun() 有参有返回函数
# in_fun() 有参有返回函数
def out_fun(x):
def in_fun(y):
return y ** x
return in_fun
print(out_fun(2)(3))
ret = out_fun(5)
print(ret(2))
#【运行结果】:
# 9
# 32
# out_fun() 无参有返回函数
# in_fun() 无参有返回函数
def out_fun():
x = 100
def in_fun():
return x + 666
return in_fun
print(out_fun()())
#【运行结果】:
# 766
# out_fun() 无参有返回函数
# in_fun() 无参有返回函数
def out_fun():
x = 100
def in_fun():
return x + 666
return in_fun()
print(out_fun())
#【运行结果】:
# 766
作者:飞翔的煤气罐boom