一、函数的定义与目的
1、函数的定义
函数是具有一定功能,并对其功能实现封装的代码。
2、函数的目的
函数的目的是为了提高代码的复用,减少代码的重复编写,增加代码的灵活性。
二、函数的相关术语
1、函数的声明
def 函数名():
pass
def my_def():
"""
这是一个自定义函数
"""
print('函数体')
函数名的命名方式按照变量的命名规则
2、函数的调用
函数名()
# 函数调用
my_def()
3、形参和实参
形参在函数声明的小括号中。
实参在函数调用的小括号中。
函数的形参可以传入多次,函数的实参要和形参相对应,按照顺序赋值。
def wakeup(name, num):
"""
这里写函数的功能
:param name: 这里写每个函数的功能
:param num:
:return: 这里写返回值
"""
for i in range(num):
print(f'第{i+1}次,叫醒:{name}')
print('*************')
wakeup('张三', 4)
4、函数的返回值
返回值可以是一个,也可以是多个。返回一个参数时,返回原类型,多个参数返回时,返回的是元组。
def fun():
return True, 200
r = fun()
print(r, type(r))
# (True, 200) <class 'tuple'>
三、初试函数
1、自定义一个函数,求两个数中的最大值
def my_max(first, second):
"""
这里写函数的功能
:param first:第一个形参
:param second: 第二个形参
:return: 返回值
"""
max_num = first if first > second else second
return max_num
r = my_max(0.55, 3.14)
print(r)
print(my_max(8, 10))
# 3.14
# 10
2、封装一个函数 求从start到stop之间相度为step的质数对。
def zs_num(start, stop, step):
# 方法二:控制结束:for i in range(start, stop - step+ 1):
for i in range(start, stop + 1):
for j in range(2, i):
if i % j == 0:
break
else:
# 方法一:控制stop
if i + step < stop:
for k in range(2, i + step):
if (i + step) % k == 0:
break
else:
print(f'{i},{i + step}')
zs_num(2, 100, 6)
将是否为质数的模块写为函数
def is_prime(num):
"""
判断是否是质数
:param num: 传入要判断的参数
:return:返回是否为质数
"""
for j in range(2, num):
if num % j == 0:
# # 方法一:
# break
# 方法二:
return False
else:
return True
def zs_num(start, stop, step):
"""
求质数对
:param start: 开始值
:param stop: 结束值
:param step: 步长
:return: 返回质数对
"""
result = []
for i in range(start, stop - step + 1):
# # 方法一:
# if is_prime(i):
# if is_prime(i + step):
# 方法二:
if is_prime(i) and is_prime(i + step):
result.append((i, i + step))
return result
r = zs_num(2, 1000, 18)
print(r)
四、函数调试
1、步过F8: 跳过函数,执行下一步。
2、步入F7: 执行自己编写的函数。
系统自带函数不用自己调试。
3、步出shift+F8:跳出函数。
4、恢复F9: 跳到下一个断点。
def f2(a, b):
print('f2开始执行')
for i in range(5):
print(f"f2中的循环第{i}次执行")
value = a + b
return value
def f1(a, b):
print(a, b)
print(f"打印最大值:{max(a, b)}")
print('开始调用f1')
r = f2(a, b)
return f"返回f1的结果:{r}"
r1 = f1(10, 20)
print(r1)
# 10 20
# 打印最大值:20
# 开始调用f1
# f2开始执行
# f2中的循环第0次执行
# f2中的循环第1次执行
# f2中的循环第2次执行
# f2中的循环第3次执行
# f2中的循环第4次执行
# 返回f1的结果:30
五、函数变量的作用域
1、函数内可调用外部变量————外部变量需要定义在调用前。
(1)、定义在函数内的变量,函数外不可以使用(函数外不能调用函数内的m,a)
def f1(m):
a = 10
print(m)
m = a + 2
c = a + b
print(c)
return m
# 定义在函数内的变量,函数外不可以使用(函数外不能调用函数内的m,a)
b = 12
# 定义在函数外的变量,函数内可以使用,不可以放在执行后
print(f1(5))
# 5
# 22
# 12
(2)、函数内定义的变量与函数外定义的变量重名,也只是有一个新的内存空间 。
- 函数内对于外部变量,不能先获取,后赋值/使用
a = 10
print(id(a))
def f1():
# 函数内对于外部变量,不能先获取,后赋值/使用
# 如:
# print(a)
# a = 25
# 函数内定义的变量与函数外定义的变量重名,也只是有一个新的内存空间
a = 20
return a, id(a)
print(id(a))
print(f1())
# 140729842000968
# 140729842000968
#(20, 140729842001288)
2、若改变外部变量,需要添加global关键字。
- global 关键字,可以在函数内部修改函数外部的变量
def f1():
# print(f"函数内部,没使用global之前:{a}, {id(a)}")
# 声明全局变量之前不可调用原来的外部变量
# 调用全局变量也要在声明之后
global a
print(f"函数内部,没使用global之前:{a}, {id(a)}")
a = 20
print(f"内部,使用global:{a}, {id(a)}")
f1()
print(f"函数执行完之后,外部:{a}, {id(a)}")
# 执行前,外部:10, 140730276832328
# 函数内部,没使用global之前:10, 140730276832328
# 内部,使用global:20, 140730276832648
# 函数执行完之后,外部:20, 140730276832648
3、不推荐在循环外部使用循环内部的局部变量。
五、函数的参数
- 一个形参只能赋值一次,不能既有位置参数的赋值,又有关键字参数的赋值
- 没有关键字的参数,必须有实参传入
1、位置参数
按照位置依次赋值。
def my_fun(a, b, c):
print(a, b, c)
my_fun(1, 2, 3)
# 1 2 3
2、默认参数
def f1(a, b, c=200):
print(a, b, c)
f1(10, 20, 30)
f1(5, 6)
# 10 20 30
# 5 6 200
(1)、默认值的例子:print(sep = " ", end = "\n")中有默认以空格分割,以换行结尾。
print(1, 2, 3, 4, 5, sep=" ", end="\n")
print(1, 2, 3, 4, 5, sep="+", end="\n")
# 1 2 3 4 5
# 1+2+3+4+5
(2)、默认参数写在最后,且可以有多个。
(3)、实参给默认参数赋值时,用实参给的值;不给时,使用默认值即可。
def f1(a, b, c=0, d='默认值'):
print(a, b, c, d)
f1(1, 2, 3)
f1(6, 7, 8, '实参赋值时,会使用实参')
# 1 2 3 默认值
# 6 7 8 实参赋值时,会使用实参
3、关键字参数
(1)、关键字参数允许通过名称指定函数参数的值,而不是按照它们在函数定义中的顺序传递参数。
(2)、关键字参数必须跟随在位置参数后面。
def f1(a, b, c=6):
print(a, b, c)
# 关键字参数必须跟随在位置参数后面
f1(b=7, a=8, c=9)
# 8 7 9
(3)、还可以在函数定义时指定某些参数的默认值,使其成为可选参数。
def greet(name, message='hello'):
print(f'{message},{name}!')
greet(name='Alice')
greet(name='Bob', message='Hi')
# hello,Alice!
# Hi,Bob!
4、可变元组
(1)、用*加形参代表可变元组参数,一般用*args。
(2)、可变元组可接收任意个参数,以元组的形式储存。
(3)、调用函数时,我们可以传递任意数量的位置参数给 *args,它们将被打包成一个元组传递给函数。
def f1(a, b, c, *args):
print(a, b, c, args, *args, type(args))
return args
f1(10, 20, 30, 40, 50)
print(f1)
# 10 20 30 (40, 50) 40 50 <class 'tuple'>
# <function f1 at 0x0000022DBFA79C60>
(4)、在函数内部可以通过遍历args元组来访问传递的参数值。
def my_f(*args):
for arg in args:
print(arg)
my_f('a', 'b', 'c', 'd', 'e')
# a
# b
# c
# d
# e
5、可变字典参数
(1)、**kwargs 允许函数接受任意数量的关键字参数,并将它们作为一个字典传递给函数。
def my_fun(a, b, f=5, **kwargs):
print(a, b, f, kwargs, type(kwargs))
my_fun(a='你好', b=2, c=None, d=4, e=5)
# 你好 2 5 {'c': None, 'd': 4, 'e': 5} <class 'dict'>
(2)、在函数内部,可以通过访问 kwargs 字典的键值对来获取传递的参数值。
def my_function(**kwargs):
for key, value in kwargs.items():
print(key, value)
my_function(fruit='apple', color='red', price=1.99)
# fruit apple
# color red
# price 1.99
6、*args和**kwargs可以与其他参数一起使用,但是通常约定将它们放在最后。
def my_fun(a, *args, **kwargs):
print(a, args, kwargs)
my_fun(3, 4, 5, 6, 7, b=10, c=bool, e=3.14)
# 3 (4, 5, 6, 7) {'b': 10, 'c': <class 'bool'>, 'e': 3.14}
六、匿名函数
lambda 匿名函数(没有函数名)
1、格式
(1)、lambda 形参:返回值
即:lambda 参数列表,多个参数使用逗号隔开 : 返回值只支持简单表达式
- 形参可以是多个,返回值只能有一个
- 形参可以省略,但是必须有返回值
- 调用时,和普通函数操作一样
f4 = lambda: print('可以只有返回值,不传参数')
f4()
f5 = lambda a, b: a if a > b else b
print(f5(10, 20), type(f5(10, 20)))
print(f5('a', 'g'), type(f5('a', 'g')))
# 20 <class 'int'>
# g <class 'str'>
2、应用场景:通常作为实参赋给形参
- 将匿名函数赋予函数中,在函数中调用匿名函数使用;相当于在函数中调用另一个比较简单的函数。
def f1(n, f):
for i in range(n):
f()
f1(5, lambda: print('匿名函数'))
# 匿名函数
# 匿名函数
# 匿名函数
# 匿名函数
# 匿名函数
3、实战
(1)、使用sort() 方法,根据列表中元素的长度,对列表进行排序。
思路:
- 使用 lambda 函数作为 sort() 方法的关键字参数来对列表进行排序。
- 使用 len() 函数作为排序的依据,表示按照字符串长度递增的顺序排序。
- 最后,使用 print() 函数打印输出排序后的列表。
# 使用 lambda 函数对列表中的元素进行排序
fruits = ["apple", "banana", "cherry", "date"]
# 将fruits中的每个元素赋予x,返回x的长度;根据长度排序
fruits.sort(key=lambda x: len(x))
print(fruits)
# ['date', 'apple', 'banana', 'cherry']
注意:sort中的key参数
- 在 Python 中,list 对象的 sort() 方法用于对列表中的元素进行排序。其中,key 是一个可选参数,用于指定排序的依据。
- 如果省略了 key 参数,则默认按照元素的大小进行排序,即按照元素的自然顺序进行排序(例如,数字从小到大,字符串按照字典序排序)。
- 如果指定了 key 参数,则应该传递一个函数作为参数,该函数将被用于计算每个元素的排序键值。sort() 方法将根据排序键值对元素进行排序,并返回排序后的列表。
- 即key重新定义排序方式
(2)、使用maxt() 方法,根据列表中字典的信息,找出以名字排序最大的字典,以及年龄最大的字典信息。
l = [{"name": "a", "age": 100},
{"name": "b", "age": 80},
{"name": "c", "age": 60},
{"name": "d", "age": 30}
]
# # 打印名称最大字典
print(max(l, key=lambda e: e['name']))
# # 打印最大年龄字典
print(max(l, key=lambda e: e['age']))
# {'name': 'd', 'age': 30}
# {'name': 'a', 'age': 100}
使用匿名函数相当于再次定义一个普通函数
def f1(e):
"""
一个一个遍历列表
:param e: 列表中的每一项
:return: 返回每一项的age
"""
return e['age']
print(max(l, key=f1))
# {'name': 'a', 'age': 100}
七、递归函数
- 要求有出口
- 自己调用自己
1、getrecursionlimit():获取递归深度;setrecursionlimit()修改递归最大深度
import sys
# 获取递归深度
print(sys.getrecursionlimit())
# 1000
# 修改递归最大深度
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
2、实战
(1)、求前100项的累加和。
def f(n):
"""
累加和
:param n: 加到几
:return: 返回自己
"""
# 递归出口
if n == 1:
return 1
else:
# 本函数调用本函数
return n + f(n - 1)
print(f(100))
(2)、求前5项的阶乘
def f(n):
"""
阶乘和
:param n: 乘到n
:return: 返回自己直到1
"""
if n == 1:
# 递归出口
return 1
else:
# 递归调用自己
return n * f(n - 1)
print(f(5))
(3)、求斐波那契数列的第7个数
def f(n):
if n == 1 or n == 2:
return 1
else:
return f(n-1) + f(n-2)
print(f(7))
八、函数的实战
1、封装函数求1+2+3+...+100的和
def total(num):
"""
求1+2+3+...+n的和
:param num: 输入的数值
:return: 数值的总和
"""
total_num = 0
for i in range(1, num + 1):
total_num += i
return total_num
n = int(input("请输入一个数:"))
print(f'和为:{total(n)}')
2、封装函数包含两个形参start与end 返回start到end之间奇数的和
def odd_num(start, end):
"""
返回start到end之间奇数的和
:param start: 起始数
:param end: 结束值
:return: 奇数和
"""
total = 0
for i in range(start, end + 1):
if i % 2:
total += i
return total
start_num = int(input('请输入开始值:'))
end_num = int(input('请输入结束值:'))
print(f'奇数和为:{odd_num(start_num, end_num)}')
3、封装函数:可以判断一个数是否是质数
def is_prime(n):
"""
判断一个数是否是质数
:param n: 输入数
:return: 判断结果
"""
for i in range(2, n):
if n % i == 0:
return '不是质数'
else:
return '是质数'
num = int(input('请输入一个数字:'))
print(is_prime(num))
方法二:
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
# return True
num = int(input('请输入一个数:'))
r = is_prime(num)
if r == False:
print('不是质数')
else:
print('是质数')
4、封装函数:求1000以内的质数对
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
else:
return True
def is_prime_pairs(num, step):
result = []
for i in range(2, num-step+1):
if is_prime(i) and is_prime(i + step):
result.append((i, i + step))
return result
end_num = int(input('请输入结束边界:'))
step_num = int(input('请输入两数之间的步长:'))
print(is_prime_pairs(end_num, step_num))
print(len(is_prime_pairs(end_num, step_num)))
5、编写函数求start到end以内所有的相差为step的素数对
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
else:
return True
def is_prime_pairs(start, end, step):
for i in range(start, end-step+1):
if is_prime(i) and is_prime(i + step):
print(i, i + step)
start_num = int(input('请输入开始边界:'))
end_num = int(input('请输入结束边界:'))
step_num = int(input('请输入两数之间的步长:'))
is_prime_pairs(start_num, end_num, step_num)
6、斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...
(1)、编写函数返回斐波那契数列的第n个数。
def fib_num(n):
"""
返回斐波那契数列的第n个数
:param n:斐波那契数列的第n个数
:return:返回的数值
"""
first = 1
second = 1
current = None
for i in range(2, n):
current = first + second
first = second
second = current
return current
num = int(input('请输入一个数:'))
if num in [1, 2]:
print(f'第{num}个数为:1')
else:
print(f'第{num}个数为:{fib_num(num)}')
(2)、返回斐波那契数列的前n个数
def fib_num(n):
"""
返回斐波那契数列的前n个数
:param n:斐波那契数列的第n个数
:return:返回的数值
"""
first = 1
second = 1
if n == 1:
return [first]
elif n == 2:
return [first, second]
else:
result = [first, second]
for i in range(2, n):
current = first + second
result.append(current)
first = second
second = current
return result
num = int(input('请输入一个数:'))
print(fib_num(num))
7、编写一个函数,接受一个数字n作为参数,该函数可以随机生成n个整数,并返回 所有整数的最大值
def max_num(n):
"""
随机生成n个整数,返回整数列表,及所有整数的最大值
:param n:
:return:
"""
max_value = -math.inf # 也可以定义为None,if是空,将第一数值给它,不是进行比较
l = []
for i in range(n):
num = random.randint(-1000, 1000)
l.append(num)
if num > max_value:
max_value = num
print(l)
return max_value
n_num = int(input('请输入一个整数:'))
print(max_num(n_num))
8、编写一个 Python 函数,接受一个字符串作为参数,并返回该字符串中所有大写字母的数量。
def up_num(str_value):
"""
返回字符串中所有大写字母的数量
:param str_value: 输入的字符串
:return: 字符串中所有大写字母的数量
"""
count = 0
for e in str_value:
# 方法一:
# if 'A' <= e <= 'Z':
# 方法二:
if e.isupper():
count += 1
return count
my_str = input('请输入一个字符串:')
print(up_num(my_str))
9、编写函数,接受一个字符串和一个字符作为参数,并返回该字符串中该字符出现的次数。
方法一:
def find_num(str_value, char_value):
return str_value.count(char_value)
方法二:
def find_num(str_value, char_value):
"""
返回字符串中该字符出现的次数
:param str_value: 输入的字符串
:param char_value: 查找的字符
:return: 字符出现的次数
"""
count = 0
for e in str_value:
if e == char_value:
count += 1
return count
my_str = input('请输入一个字符串:').lower()
my_char = input('请输入一个字符:').lower()
print(find_num(my_str, my_char))