1.函数
1.1 函数的定义
函数的定义:实现【特定功能】的代码块。
函数的作用:
-
- 简化代码
- 提高代码重用性
- 便于维护和修改
- 提高代码的可扩展性
函数的三要素:
-
- 功能 len() max() sum()
- 参数 s.clear() s.append('hello')
- 返回值 s.sort() s1 = sorted(s)
函数定义的语法格式:
函数的分类:
-
- 从定义角度—— 内置函数【别人写好的,你直接用】 自定义函数
- 从参数角度—— 无参函数 有参函数
- 从返回值角度——无返函数 None 有返函数
函数的调用/使用:
1.无返函数 | 函数名( ) | fun() |
2.有返函数 | 方法1:print(函数名()) 方法2:变量名 = 函数名() | print(fun()) ret=fun() |
1.2 函数的参数传递
①位置参数:
传递参数时应该 和 定义时的参数 保持位置和数量一 一对应。
def fun(a, b, c):
print(a, b, c)
fun(1, 2, 3)
#运行结果 1 2 3
fun('张三', 18, '男')
#运行结果 张三 18 男
fun([1,2,3], (4,5,6), {7,8,9})
# 运行结果 [1, 2, 3] (4, 5, 6) {8, 9, 7}
def fun(a:int, b:float, c:str):
print(a, b, c)
# 有警告,无报错,以实际传参为准
fun(1, 2, 3)
fun(3.15, 7, [1,2,3])
②关键字参数:
调用函数传递参数时,按照 参数名=值 的方式,传参的顺序可以和定义参数的顺序不一致。
def fun(name, age, sex):
print(name, age, sex)
# 关键字参数
fun(name='张三', age=18, sex='男')
fun(age=18, sex='男', name='张三')
③默认参数:
在函数定义时给参数设置默认值,那么在函数调用时,若不传参就是用默认值,若传参就是用传参的值。
def fun(name='张三', age=18, sex='男'):
print(name, age, sex)
# 默认参数
fun()
fun('李四')
fun(age=66)
fun('小明', 30)
fun('小华', 23, '女')
④位置不定长参数:
在定义函数时参数名前加 * ,也就是def fun( *args ),那么在传参的时候就可以传若干个位置参数。将参数打包成——元组。
def fun(*num):
print(num)
fun(1)
fun(1,2,3,4,5,6)
# 问:在一个函数中,位置不定长参数,可以有两个吗?
# 不允许
# 再问:一旦定义了位置不定参参数,是不是就不可以定义其他参数了呢?
# 答:可以定义,但是传参时必须是关键字参数
def test(*num, a, b):
print(num)
print(a)
print(b)
test(1,2,3,4,a=5,b=6)
def test1(a, b, *num):
print(a)
print(b)
print(num)
test1(1, 2, 3,4,5,6,7)
def test2(a, *num, b):
print(a)
print(num)
print(b)
test2(1, 2,3,4,5, b=66)
⑤关键字不定长参数:
在定义函数参数名前加 ** ,也就是 def fun( **kwargs ),那么传参的时候就可以传若干个 关键字参数。将参数打包成——字典。
def fun(**kwargs):
print(kwargs)
fun(a=12, b=13, c=15)
fun(姓名='张三', 年龄=18, 性别='男')
※ 练习题:
(1)定义函数,参数为位置可变长参数, 请将传入的所有实参按照升序输出
def fun( *num ):
print(sorted(num))
fun(5,8,3,6,2,0)
(2)定义函数,参数为关键字可变长参数,请将其中HuaHua的身高修改为160, 然后打印出所有身高不足180的姓名, 使用fun(XiaoMing=155,XiaoHong=171,XiaoHei=192,HuaHua=2333)调用测试
def fun(**stu):
if 'huahua' in stu:
stu['huahua']=160
print(stu)
for name in stu.keys():
if stu[name]<180:
print(name)
1.3 函数的返回值
- 如果函数的运行结果想在函数外使用,就需要设置返回值。
- 使用关键字 return 进行返回。
- return 可以在函数中出现多次,但是只执行 1 次,遇见return返回值并结束函数。
- 与C语言不同,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, type(ret))
※ 简单函数练习题
(1)定义函数,无参无返,可求出200以内所有包含7的数字(5分)
def fun():
for i in range(0,200):
if '7'in str(i) :
print(i)
fun()
(2)定义函数,无参有返,可返回200-300所有偶数组成的数列(5分)
def fun():
for i in range(200,301):
if i%2==0:
print(i,end=" ")
fun()
(3)定义函数,有参无返,可接收任意一个字符串,并计算该字符串有几个字符(5分)
def fun(*str):
s=input("输入字符串:")
print(len(s))
fun()
(4)定义函数,有参有返,可接收任意一个字符串,对其进行去重,返回去重后的集合(5分)
def fun(*str):
s=input("输入字符串:")
print(set(s))
# return
print(fun())
(5)定义函数, 可输入一个字符串,并打印出其中的所有数字(5分)
def fun(*str):
s=input("输入字符串:")
for number in s:
if number.isdigit():
print(number,end=" ")
fun()
(6)定义函数,可接收一个数字列表,并返回其中的最大值和最小值, 要求:不可以在自定义函数内调用max和min函数(5分)
def fun(*num):
l_max=num[0]
l_min=num[0]
for i in num:
if l_max<i:
l_max=i
elif l_min>i:
l_min=i
return l_min,l_max
ret=fun(5,8,3,6,0)
print(ret)
(7)定义函数,可打印三行四列矩形(5分)
def print_rectangle(rows=3, cols=4):
for i in range(rows):
for j in range(cols):
print('*', end=' ')
print() # 换行
print_rectangle()
(8)定义函数,计算1-100的所有数字的和(5分)
def fun():
sum=0
for i in range(1,101):
sum=sum+i
print(sum)
fun()
(9)定义函数,可打印9行9列的等腰直角三角形(5分)
def print_right_angle_isosceles_triangle(height):
"""
打印一个给定高度的等腰直角三角形。
参数:
height (int): 等腰直角三角形的高,也是底边除直角顶点外半边的长度。
不返回任何值,仅打印三角形到控制台。
"""
for i in range(1, height + 1):
# 每一行开始先打印空格
for j in range(height - i):
print(' ', end='')
# 接着打印星号构成斜边
for k in range(i):
print('*', end='')
print() # 换行
# 调用函数打印一个高度为9的等腰直角三角形
print_right_angle_isosceles_triangle(9)
(10)定义函数,参数为非关键字可变长参数,请将传入的所有实参按照降序输出
def fun(*args):
# 使用sorted函数对参数进行降序排序
sorted_args = sorted(args, reverse=True)
print("降序排列后的参数:", sorted_args)
# 示例调用
fun(3, 1, 4, 1, 5, 9, 2, 6)
(11)定义函数,参数为关键字可变长参数,请计算并返回他们的平均身高, 使用(xiaoming='178cm',xiaobai='182cm',xiaohong='166cm',xiaohei='174cm')
def fun(**stus):
n=0
sum=0
for i in stus.values():
sum+=int(i.split('cm')[0])
n+=1
return sum/n
ret=fun(xiaoming='178cm',xiaobai='182cm',xiaohong='166cm',xiaohei='174cm')
print(f"平均身高{ret}cm")
1.4 递归函数
问:一个函数的调用放在哪里?——函数外
# 要求定义一个递归函数,实现输出N遍"我爱python"
def rec(N:int):
if N==0:
return
else:
print(f"{N}我爱python")
rec(N-1)
rec(10)
递归函数有三要素:
① 边界条件/基线条件 跳出/结束递归的条件
② 递归返回段 满足结束条件时,返回
③ 递归前进段 不满足结束条件时,前进/继续递归
# 定义一个递归函数,求n的阶乘
# 阶乘:就是累乘,从1累乘到本身 或者从本身累乘到1
# 5! = 1*2*3*4*5 = 5*4*3*2*1
def rec(n):
"""
求一个数n的阶乘
:param n: 接收到一个整型值
:return: 计算的阶乘结果
"""
if n==1:
return 1
else:
return n * rec(n-1)
n = 5
print(rec(n))
※ 递归函数练习题
(1)求第6个斐波那契数
def fb(n):
if n == 1 or n == 2:
return 1
else:
return fb(n-1)+fb(n-2)
print(fb(6))
(2)使用递归函数求5的阶乘
# 定义一个递归函数,求n的阶乘
# 阶乘:就是累乘,从1累乘到本身 或者从本身累乘到1
# 5! = 1*2*3*4*5 = 5*4*3*2*1
def rec(n):
"""
求一个数n的阶乘
:param n: 接收到一个整型值
:return: 计算的阶乘结果
"""
if n==1:
return 1
else:
return n * rec(n-1)
n = 5
print(rec(n))
(3)使用递归函数求50-100的总和
def sum_recursive(start, end):
# 基准情况:如果起始值大于结束值,直接返回0
if start > end:
return 0
# 递归情况:当前起始值加上剩余范围的和
else:
return start + sum_recursive(start + 1, end)
# 调用函数计算50到100的和
total_sum = sum_recursive(50, 100)
print(f"50到100的总和为: {total_sum}")
(4)已知有5个人坐在一起,第5个人说他比第四个人大5岁, 第4个人说他比第三个人也大5岁,以此类推,第一个人说他19岁, 请问,第五个人多少岁
def age_of_person(n, first_age=19, age_difference=5):
# 递归终止条件:当索引为1时,返回第一个人的年龄
if n == 1:
return first_age
# 递归调用:计算前一个人的年龄,然后加上年龄差
else:
return age_of_person(n - 1, first_age, age_difference) + age_difference
# 计算第五个人的年龄
fifth_person_age = age_of_person(5)
print(f"第五个人的年龄是:{fifth_person_age}岁")
(5)使用递归函数求n的k次方
def power(n, k):
# 递归终止条件:k等于0时,返回1
if k == 0:
return 1
# 递归步骤:如果k是正数,就计算n乘以n的(k-1)次幂
elif k > 0:
return n * power(n, k - 1)
# 如果k是负数,先处理成正数的情况,再取倒数,因为负指数相当于求正指数后的倒数
else:
return 1 / power(n, -k)
# 示例:计算2的5次方
result = power(2, 5)
print(f"2的5次方是:{result}")
(6)使用递归函数判断一个字符串是不是回文字符串
def fun(s):
# 基本情况:如果字符串长度为0或1,可以直接判定为回文
if len(s) <= 1:
return True
# 检查首尾字符是否相同
if s[0] != s[-1]:
return False
# 递归地检查去掉首尾字符后的子串
return fun(s[1:-1])
# 示例:判断字符串是否为回文
example = "madam"
result = fun(example)
print(f"'{example}' 是否为回文字符串?{result}")
example2 = "hello"
result2 = fun(example2)
print(f"'{example2}' 是否为回文字符串?{result2}")
1.5 函数中变量的作用域
def fun1():
a = 10
print(a)
def fun2():
print(f"fun1函数中的{a}")
# 局部变量只能在该函数内使用
fun1()
# fun2() 报错
# print(f"fun1函数中的{a}") 报错
a = 100
def fun():
# 局部变量
a = 200
print(a)
print(a) # 100
fun() # 200
# 从这里可以看到,局部变量可以和全局变量重名,但是
# 局部变量覆盖全局变量【遵循就近原则】
1.6 函数嵌套
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}")
运行结果: 【和C语言是有区别的,可以通过绑定关键字global修改】
内函数中输出300
外函数中输出200
函数外输出100
通过上面的例子可以发现:
内函数局部变量 > 外函数局部变量 > 全局变量
对比global 和 nonlocal:
① global 修饰全局变量
② nonlocal 修饰该函数上一层的局部变量
1.7 闭包函数
什么是闭包函数?——如果内函数中使用了外函数的局部变量,并且外函数把内函数返回的过程就叫闭包。
形成闭包的条件:
- 函数嵌套
- 将内函数作为返回值返回
- 内函数必须使用外函数的局部变量