函数
一、函数的作用
-
问题引入:
问题1:功能一样的代码,需要重复写很多遍
问题2:如果功能发生改变,需要修改多处代码解决:函数
- 什么是函数
函数就是对实现某一特定功能的代码的封装(就相当于具有某种功能的机器) - 函数的分类(由谁来创建)
系统函数:由系统(Python)创建好的函数就是系统函数,程序员只需要在使用这个函数的时候调用,例如:print,input,type
自定义函数:由程序员自己创建的函数,就是自定义函数。(自己造机器) - 定义函数(创建函数) - 造机器
- 什么是函数
-
函数的语法和说明:
-
语法:
def 函数名(形参列表):
函数说明文档
函数体 -
说明:
def、()、冒号 - 固定写法
函数名 - 程序员自己定义:
标识符不是关键字;
见名知义(看到函数名,大概知道函数的功能)…
形参列表 - 以’变量名1,变量名2,变量名3…’ 形式存在,形参可以一个都没有,也可以有多个
形参的作用是将函数外部的数据传递到函数里面。(传递数据的通道)
函数说明文档 - 本质就是文档注释(’’’’’’,"""""")
函数体 - 和def保持缩进的一条或者多条语句。函数体就是实现函数功能的代码 -
步骤
第一步:确定函数功能
第二步:根据功能确定函数名
第三步:确定参数,看实现函数的功能需不需要额外的数据,需要几个。
第四步:实现函数的功能
第五步:写函数说明文档
-
-
重要结论:定义函数的时候不会执行函数体,调用函数的时候才会执行函数中的函数体
-
调用函数(使用机器)
- 语法
函数名(实参列表) - 说明
函数名 - 必须是已经定义好的函数的函数名
实参列表 - 以’数据1,数据2,…'形式存在,实参就是通过形参传递到函数内部的具体数据 - 函数的调用过程
第一步:回到函数定义的位置。
第二步:传参 (实参给形参赋值)
第三步:执行函数体
第四步:确定函数返回值
第五步:回到函数调用的位置,接着往后执行
- 语法
练习1:定义一个函数实现求任意两个数的和的功能
def add1(a, b):
"""
(功能说明区)求两个数的和
:param a: num1: (参数说明区) 数字1
:param b: num2: 数字2
:return: (返回值说明区)
"""
return a + b
# 1.求3+2的和
print(add1(3, 2)) # 5
print(add1((100))) # TypeError: add1() missing 1 required positional argument: 'b'
练习2:定义一个函数求一个数的阶乘。(n! = 1×2×3×n-1×n)
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
# 2.求5的阶乘
print(factorial(5)) # 120
练习3:定义一个函数可以统计一个字符串中空格出现的次数****
def count_space(string):
sum1 = 0
for x in string:
if x == ' ':
sum1 += 1
return sum1
# 3.统计字符串'a b c d'中空格出现的次数
print(count_space('a b c d')) # 3
练习4:定义一个函数可以统计一个字符串中另外一个字符串出现的次数
def count_char(string, string1):
count = 0
for element in range(len(string) + len(string1) - 1):
if string[element:element + len(string1)] == string1:
element += len(string1)
count += 1
return count
# 4.统计字符串'how are you? i am fine, thank you, and you?'中
# 另外一个字符串'you'出现的次数
str1 = 'how are you? i am fine, thank you, and you?'
str2 = 'you'
print(count_char(str1, str2)) # 3
二、函数的参数
-
位置参数和关键字参数(实参的分类)
说明:
- 位置参数:以’数据1,数据2,数据3,…'的形式存在,传参的时候直接和形参从位置上一一对应
- 关键字参数:以’形参名1 = 数据1,形参名2 = 数据 2,…'的形式存在
- 混用的时候位置参数必须在关键字参数的前面
例:
def fun1(a, b, c):
print(f'a:{a}, b:{b}, c:{c}')
fun1(10, 20, 30) # a:10, b:20, c:30
fun1(a=10, b=20, c=30) # a:10, b:20, c:30
fun1(b=20, a=10, c=30) # a:10, b:20, c:30
fun1(10, c=30, b=20) # a:10, b:20, c:30
fun1(10, 20, c=30) # a:10, b:20, c:30
# fun1(a = 10, 20, 30) # SyntaxError: positional argument follows keyword argument
-
参数默认值(形参)
-
定义函数的时候,可以通过’形参名 = 值’的方式给参数赋默认值。
-
有默认值的参数在调用的时候可以不用传参
-
注意:定义函数的时候所有的参数都可以有默认值,也可以部分参数有默认值,如果是部分参数有默认值,没有默认值的参数必须放前面
def fun2(a, b, c=10): print(f'a:{a}, b:{b}, c:{c}') fun2(10, 20, 30) # a:10, b:20, c:30 fun2(10, 20) # a:10, b:20, c:10 # def fun3(a=10, b, c): # SyntaxError: non-default argument follows default argument # print(f'a:{a}, b:{b}, c:{c}') def fun4(a=10, b=20, c=30): print(f'a:{a}, b:{b}, c:{c}') fun4() # a:10, b:20, c:30 fun4(100) # a:100, b:20, c:30 fun4(100, 200) # a:100, b:200, c:30 fun4(c=300) # a:10, b:20, c:300
-
-
参数类型说明
-
方法一:给参数赋默认值,默认值的类型就是对应的参数类型
-
方法二:以’形参名:类型名’的方式说明类型
-
注意:方法一和方法二不能同时使用
def fun5(names=[]): names.append(100) print(names) # 方法一 def fun5(names: list, obj: str, count=0): names.append(100) # 方法二
-
-
不定长参数
-
第一种:在参数前加这个带*的参数会变成一个元组,会将对应的实参作为元组中的元素
- 注意:在调用的时候只能使用位置参数传参
- 如果定义函数的时候定长的参数在不定长的后面,定长参数传参必须使用关键字参数
-
第二种:在参数前加**
- 这个带**的参数会变成一个字典,代用的时候使用关键字参数传参,每个关键字参数会作为字典的一个键值对。
①第一种
# 第一种: # 写一个函数求多个数的和 def sum2(*nums): s = 0 for x in nums: s += x print(s) sum2() # 0 sum2(100) # 100 sum2(10, 20) # 30 sum2(10, 20, 30, 40) # 100 def sum3(name, *scores): print(name, scores) sum3('小明', 19, 89, 78) # 小明 (19, 78, 34) # 如果定义函数的时候定长的参数在不定长的后面,定长参数传参必须使用关键字参数 def sum4(*score, name): print(name, score) sum4(19, 78, 34, name='小明') # 小明 (19, 78, 34)
-
②第二种
# 第二种:
def fun6(**nums):
print(nums)
fun6() # {}
# fun6(10) # fun6() takes 0 positional arguments but 1 was given
fun6(x=10) # {'x': 10}
fun6(x=10, y=20, a=30) # {'x': 10, 'y': 20, 'a': 30}
def fun7(*args, **kwargs): # 使用更加灵活,位置参数可,关键字参数可,混用也可
pass
def fun8(a, *, b, c): # b,c必须使用关键字传参
print(a, b, c)
fun8(10, b=23, c=9) # 10 23 9