Published in:2024-10-24 |

函数(一)

一、为什么要引入函数

  • 不使用函数,之前写一个程序

    • 一行一行地去实现代码
    • 对于大型项目,代码的可读性和维护性很差
    1
    2
    3
    4
    5
    6
    7
    8
    9
    a = int(input("请输入第一个数:"))
    b = int(input("请输入第二个数:"))
    c = a + b
    print(f"{a}+{b}={c}")

    a = int(input("请输入第一个数:"))
    b = int(input("请输入第二个数:"))
    c = a - b
    print(f"{a}-{b}={c}")

    一个大型的项目,应该分为若干个程序块(代码块),每一个代码块来实现一个特定的功能。需要有一个东西来包裹代码块 – 函数

  • 使用函数来实现计算器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # add是代码块的名字-函数名
    def add():
    a = int(input("请输入第一个数:"))
    b = int(input("请输入第二个数:"))
    c = a + b
    print(f"{a}+{b}={c}")

    # sub是代码块的名字-函数名
    def sub():
    a = int(input("请输入第一个数:"))
    b = int(input("请输入第二个数:"))
    c = a - b
    print(f"{a}-{b}={c}")
  • 函数:

    • function 翻译过来:功能
    • 定义:函数就是具有某一特定功能的代码块的“集合”.
  • 函数的目的:

    • 实现代码复用 code reuse – 多次调用
    • 实现模块化开发,代码结构层次更清晰,易读
    • 方便代码的维护

二、函数的使用

1、函数的定义
1
2
3
4
5
6
7
8
9
# 函数名(标识符名):功能模块的名字,望文知意
# 每个单词小写,单词与单词之间用_连接 this_is_a_function
# 或 除首字母外的所有单词的首字母都大写 thisIsAFunction
def 函数名():
实现功能的代码块(函数体的代码)

# 写一个打招呼的函数
def greeting():
print('hi,My name is Mr_lee!')
2、函数的调用
1
2
greeting()    # 函数名()
greeting() # 多次调用
  • 函数的运行机制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Python代码是从下往下逐行执行
a = 5
b = 10
print(a,b)

# 执行到这里时,函数内部的代码并不会被执行
def greeting():
print('hi,My name is Mr_lee!')

print("函数已经定义了")

greeting() # 函数调用时,会跳转到函数定义的地方,进入函数内部,执行里面的代码,执行完毕后再跳回到函数调用的地方,继续执行后面的代码

print("over") # 调用完greeting函数后,执行over

程序的运行结果:

1
2
3
4
5 10
函数已经定义了
hi,My name is Mr_lee!
over
1
2
# Python内置了一些函数 Python的作者
len([2,3,4]) # 函数的调用

三、函数的参数和返回值

1、函数的参数

可以把函数比作一个加工厂(面包加工厂),加工厂只负责加工产品,在加工产品需要有原材料,而原材料一般都由外界提供

1
2
3
4
5
def add():
a = int(input("请输入第一个数:")) # 原材料是在加工厂内部产生
b = int(input("请输入第二个数:"))
c = a + b
print(f"{a}+{b}={c}")

修改后:

1
2
3
4
5
6
7
def add(a,b):
c = a + b
print(c)

x = 3
y = 5
add(x,y) # 当调用函数时,从外界把数据传递给函数
  • 形参:形式参数,函数定义时的参数。最开始没有值,值是从实参传过来
  • 实参:函数调用时,实际传递给函数的参数 (实参传给形参)
2、函数的返回值

函数相当于一个加工厂,加工厂加工完产品之后,需要送出去

1
2
3
4
5
def add(a,b):
c = a + b
print(c)

add(3,5)

修改后:

1
2
3
4
5
6
7
8
9
10
def add(a, b):
c = a + b
return c # return 返回

result = add(3, 5)
print(result)
# 这里并不是把函数赋值给变量result 而是将函数的返回值赋值给result result = c

result = add() # error 定义了形参 调用函数时传递的实参的个数要和形参的个数保持一致
print(result)
1
2
3
4
# len()函数的用法
t = [2,4,6,8]
l = len(t)
print(l)
  • 如果函数没有定义返回值,默认返回为None return None

小结:

函数的几个基本形式:

  • 没有参数,也没有返回值

    1
    2
    3
    4
    def func():
    print('this is a function~~~')

    func()
  • 有参数,但没有返回值

    1
    2
    3
    4
    def func(a,b,c):
    print(a,b,c)

    func(2,3,5) # 实参的个数要和形参的个数保持一致
  • 有参数,也有返回值

    1
    2
    3
    4
    5
    6
    7
    8
    def func(a,b):
    return a+b

    func(3,5)
    result = func(3,5)
    print(result)
    print(func(3,5))
    print(func)

四、参数的详解

1、位置参数
1
2
3
4
5
6
def add(a, b):
return a + b


result = add(5,10) # 形参的实参的个数、位置是一一对应的 5->a 10->b
print(result)
2、关键字参数
1
2
3
4
5
6
7
8
9
10
def add(a, b):
print(a,b)
return a + b

result = add(5,10) # a=5 b=10
print(result)

# 调用函数时,通过关键字的形式给形参赋值
result = add(b=5,a=10) # a=10 b=5
print(result)
  • 位置参数和关键字参数混合时需要注意:
    • 保证每一个形参都可以获取到值
    • 位置参数要放在关键字参数的前面
3、参数(形参)的默认值

定义函数时,可以给函数的形参赋一个默认的值

  • 给所有的形参默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def add(a=3,b=5):
return a+b

# 1. 调用函数时,不传递实参
result = add() # 8
print(result)

# 2. 参数一个实参,赋值时是从左向右进行 位置参数 所以1赋值给了a
result = add(1) # 6
print(result)

# 3. 传两个参数,把a和b的值覆盖掉
result = add(2,3) # 5
print(result)
  • 给一部分形参默认值
1
2
3
4
5
6
# 前一参数有了默认值,后面所有的形参都必须有默认值
def add(a,b=5,c=3):
return a+b

result = add(3)
print(result)
4、可变长参数

定义函数时,不确定将来函数调用时会传递多少个参数

  • *args :函数调用时,传递的实参不受个数的限制,实参会被存放在元组中-args
1
2
3
4
5
6
7
8
9
def f(*args):     # 形参名:约定俗成 也可以定义成其它的名字
print(args)
for i in args:
print(i)


f(1)
f(1, 2, 3)
f(1, 2, 3, 4, 5, 6, 7, 8, 9, 90, 0)
  • **kwargs: 可变长的关键字参数,函数调用时使用关键字参数传参,kwargs会生成为字典
1
2
3
4
5
6
def f(**kwargs):
print(kwargs)
print(kwargs['a'])


f(a=1, b=2, c=3)
  • 可变长位置参数和关键字参数混合使用
1
2
3
4
5
6
7
def f(*args, **kwargs):
print(args)
print(kwargs)

f(1, 2, 3)
f(1, 2, 3, x=4, y=5, z=6)
f(x=4, y=5, z=6)

函数注释:

1
2
3
4
5
6
7
8
def add(a,b):
"""
这是一个两个数相加的函数
:param a: 第一个参数
:param b: 第二个参数
:return: 返回两个数相加的和
"""
return a+b

练习:

  • 写一个函数,实现输入一个整数n,求它的阶乘
1
2
3
4
5
6
7
8
9
10
11
12
def f(n):
factorial = 1
for i in range(1, n + 1):
factorial *= i
return factorial

# 1. 输入数据
# 2. 调用函数
# 3. 输入结果
a = int(input('请输入一个整数n:'))
factor = f(a)
print(factor)

五、函数的嵌套调用

函数的嵌套调用是指在一个函数中,调用另一个函数

1
2
3
4
5
6
7
8
def f1():
print(123)

def f2():
print(456)
f1()

f2()

什么情况下会使用到函数的嵌套调用:

​ 一个函数的功能实现比较复杂,可以将该函数再分解为若干个小的功能模块(函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 打印1-100以内所有的质数

# 判断是不是质数
def is_prime(n):
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
else:
return True

# 打印100以内的质数
def print_prime():
for i in range(2,100):
if is_prime(i):
print(f'{i}是质数')


print_prime()

六、内嵌函数

内嵌/内置/内部函数 inner function : 在一个函数的内部,再去定义另一个函数

1
2
3
4
5
6
def f1():
print('this is f1')
def f2():
print('this is f2')

f1() # 只输出f1
1
2
3
4
5
6
7
8
9
10
def f1():
print('this is f1')

def f2(): # f2只在f1函数的内部是可见的
print('this is f2')

f2()


f1() # 输出f1 和 f2

七、递归函数

递归:一个函数调用它自身 (画中画)

1
2
3
4
5
def func():
print('哈哈哈哈')
func()

func()
1
2
3
4
5
6
7
# 递归求n!
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)

print(factorial(5))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 不用递归
a = 1
b = 1
for i in range(10):
#a,b = b,a+b
result = a + b
a = b
b = result
print(result)

# 递归求斐波那契数列
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2) # f(4) = f(3)+f(2)

for i in range(1,11):
print(fib(i))
Prev:
Next: