课程导入
有一天,你有一个需求:统计两个班级的《python程序》课程成绩,计算各自的最高分、总分。
在你学习函数之前,你很可能这么写:
class1 = [77, 88, 100, 66, 45, 65, 32, 78, 89, 90, 94, 90]
class2 = [45, 67, 89, 87, 63, 79, 97, 90, 91, 43, 69, 23, 80, 99]
# 统计1班最高分、总分
max1 = 0
sum1 = 0
for one in class1:
if one > max1:
max1 = one
sum1 += one
print("1班最高分:", max1, "总分:", sum1)
# 统计2班最高分、总分
max2 = 0
sum2 = 0
for two in class2:
if two > max2:
max2 = two
sum2 += two
print("2班最高分:", max2, "总分:", sum2)
然后你会发现,你的重复代码几乎占了50%,如果要统计n个班级,这里的重复代码就要写n遍。
所以,可不可以把一个程序中重复率高的代码写成一种公共的样式,用的时候“套公式”呢?当然可以,
这就是——函数。
上述代码可改写如下(这段代码并不优美,但是是初学阶段最容易理解的写法):
def tj(listData):
m = 0
s = 0
for i in listData:
if i > m:
m = i
s += i
print("最高分:", m, "总分:", s)
class1 = [77, 88, 100, 66, 45, 65, 32, 78, 89, 90, 94, 90]
class2 = [45, 67, 89, 87, 63, 79, 97, 90, 91, 43, 69, 23, 80, 99]
print("1班", end="");tj(class1)
print("2班", end="");tj(class2)
函数概念
函数:把一个程序中重复率高的代码写成一种公共的、可重复调用的样式,此样式即为函数,使用def关键字声明。格式如下:
def 函数名称(参数): # 代码 # return 值,这个返回值可能有,也可能没有
辅助理解:我要吃蛋糕,我需要给蛋糕店(函数)提供一些信息,比如我需要多大的蛋糕、放哪些水果(参数),然后蛋糕店(函数)给我它处理完成的结果(蛋糕),这个蛋糕,就是返回值。至于这个过程中蛋糕是怎么做出来的,我不需要知道,蛋糕店(函数)知道即可。
示例:比较数字、字符串:
def max(a, b):
return a if a > b else b
print("比较数字:", max(1, 88))
print("比较字符串:", max("zyx", "abcd"))
说明文档
程序员代码规范中,需要给自定义的函数写一个总注释,用来解释这个函数的功能。
其他程序员在调用这个函数时,可以通过help(函数名称)或函数名称.__doc__的方式获取该注释。
def max(a, b):
'''
这个函数可以比较数字大小、字符串长度,返回最大或最长的数据
'''
# 我是一般的注释
return a if a > b else b
help(max)
print("**********")
print(max.__doc__)
结果:
Help on function max in module __main__:
max(a, b)
这个函数可以比较数字大小、字符串长度,返回最大或最长的数据
**********
这个函数可以比较数字大小、字符串长度,返回最大或最长的数据
[Finished in 61ms]
参数详解
形参&实参
函数的参数,有形式参数(形参)和实际参数(实参)之分。这说法考试常见,但实际工作中直接说“参数”更多。
- 形参:函数声明的时候的参数,跟def出现在一起,是一个数据名字
- 实参:函数使用的时候的参数,是传给函数的具体数据
def add(a, b): # a, b为形参
return a + b
print(add(10, 11)) # 实参
print(add("hello", "world")) # 实参
值传递&引用传递
- 值传递:传给函数的是数值,即不可变数据类型:数字、字符串、元组
- 引用传递:传给函数的是地址,即可变数据类型:列表、字典
例1:值传递传给函数的是变量的值,这个值在函数内部做的任何操作,都不会影响原始变量。
def change(a, b):
a = 0
b = 'xyz'
a = 10; b = 'abc'
change(a, b)
print(a, b) # 10 abc
例2:引用传递传给函数的是地址,如果对这个地址上的数据进行了修改,那么对于所有引用这个地址的变量,相应位置的值都会改变。
def change(a, b):
a[0] = 0
b[1] = 'x'
a = [10, 11, 12]; b = {1:'a', 2:'b'}
change(a, b)
print(a, b) # [0, 11, 12] {1: 'x', 2: 'b'}
位置参数(必备参数)
是参数个数在声明时就固定了的一种参数类型(本篇上述函数全部都是)特点:
- 形参和实参数量必须一致
- 形参和实参位置必须一致,数据类型1:1对应的上才行
关键字参数
使用形参名字来声明哪一个实参是自己,因此不需要保证形参和实参位置一致:
def change(a, b, c):
print(a, b, c)
# 位置参数
change(10, 'abc', (99,)) # 10 abc (99,)
# 关键字参数 认识一下
change(a=10, b='abc', c=(99,)) # 10 abc (99,)
change(b=10, a='abc', c=(99,)) # abc 10 (99,)
# 关键字参数 搞事情写法
# change(a=10, b='abc', (99,)) #SyntaxError: positional argument follows keyword argument
change(10, b='abc', c=(99,)) # 10 abc (99,)
change(10, c='abc', b=(99,)) # 10 (99,) abc
# change(10, 'abc', b=(99,)) #TypeError: change() got multiple values for argument 'b'
SyntaxError原因:位置参数必须在关键字参数前面。
TypeError原因:b参数在末尾声明,于是默认b前面的10, ‘abc’, 都是a的值,继而报错。
默认值参数
形参在声明的时候,可以给定默认值。如果使用该函数的时候实参也给了值,会覆盖默认值,如果没给,那么函数内部根据默认值执行。
def change(a, b, c=100):
print(a, b, c)
change(10, 11) # 10 11 100
change(10, 11, 12) # 10 11 12
# 又来搞事情
change(a=10, b=11) # 10 11 100
# change(a=10) # TypeError: change() missing 1 required positional argument: 'b'
⚠️:带有默认值参数的函数,在声明的时候必须把默认值放在参数最后面,否则:
def change(a, b=100, c): # SyntaxError: non-default argument follows default argument
获取函数默认值
可以使用“函数名.defaults”查看函数的默认值参数的当前值,其返回值是一个元组。
def change(a, b=2, c=3):
a = 10; b = 20; c = 30
print("函数内部:change.__defaults__ =", change.__defaults__)
change(100, 200, 300)
print("函数外部:change.__defaults__ =", change.__defaults__)
结果,两个输出都是 (2, 3)
可变参数
有时候,参数个数我们自己都不知道,可能传2个,也可能传3个,你可以这样写(用的少,暂时写这么多,认识即可):
可变位置参数*args
def sum_numbers(*args):
sum = 0
for num in args:
sum += num
return sum
print(sum_numbers(1, 2, 3)) # 6
可变关键字参数**kwargs
def configure(a, b, **kwargs):
print(f"a: {a}, b: {b}")
for key, value in kwargs.items():
print(f"可变关键字参数:{key}: {value}")
configure("www.baidu.com", b=8080, use_ssl=True)
print()
configure("admin", b=123, name="Alice", age=30, job="Engineer")
结果:
a: www.baidu.com, b: 8080
可变关键字参数:use_ssl: True
a: admin, b: 123
可变关键字参数:name: Alice
可变关键字参数:age: 30
可变关键字参数:job: Engineer
[Finished in 42ms]
返回值
- python函数有一个特殊的常量 None(N 必须大写)。它不表示 0,也不表示空字符串,而表示没有值,也就是空值。
- 所有看似没有return的函数,python都会在解析时在其末尾加上
return None,也就是说,没有声明返回值的函数,默认返回值都是None。 - 同一个函数中,如果出现分支(if、elif、else),可能会有多行return代码,但只要有一个return被执行,函数的执行就会全部结束。
def max1(a, b):
return a if a > b else b
def max2(a, b):
print(a if a > b else b)
print("max1返回值:", max1(1, 4))
print("max2返回值:", max2(1, 4))
结果:
max1返回值: 4
4
max2返回值: None
多个返回值
可按元组、字典return多个值:
# example1返回两数中最大值,example2返回元组,example3返回字典
def example1(a, b):
return a if a > b else b
def example2(a, b):
return a, b
def example3(a, b):
return {'a': a, 'b': b}
print(example1(1, 4)) # 4
x, y = example2(1, 4)
print(x, y) # 1 4
print(type(example2(1, 4))) # <class 'tuple'>
z = example3(1, 4)
print(z['a'], z['b']) # 1 4
1700

被折叠的 条评论
为什么被折叠?



