day10 - 函数基础
1. 函数的定义
1. 函数的概念(什么是函数)
"""
函数就是实现某一特定功能的代码的封装。
(函数就是把实现某一个功能的代码打成一个包,以后再需要这段代码对应的功能的时候不需要再写这段代码,而是直接调用封装这段的函数)
"""
2. 函数分类(函数由谁创建)
"""
1)系统函数(别人造好机器) - Python自带的函数,例如:print、input、type、max、min、sorted等
2)自定义函数(自己造的机器) - 由程序员自己创建的函数
"""
3. 定义函数/创建函数
"""
语法:
def 函数名(形参列表):
函数说明文档
函数体
说明:
def - 关键字;固定写法
函数名 - 由程序员自己名,但是必须符号命名要求和规范
要求:是标识符;不能是关键字
规范:见名知义(看到函数名就大概知道这个函数对应的功能是什么);
字母都小写多个单词用下划线隔开;
不使用系统的函数名、类名、模块名
(): - 固定写法
形参列表 - 以'变量名1,变量名2,变量名3,...'的形式存在,这儿的变量名可以有也可以没有
形参的作用:将函数外部的数据传递到函数里面
怎么确定形参:看实现函数的功能需不需要额外的数据,需要几个(在函数体中就把形参当成对应的数据来使用)
函数说明文档 - 本质就是一个多行注释,用来描述函数的功能和使用方法
函数体 - 结构上:和def保持一个缩进的一条或者多条语句(至少一条)
逻辑上:函数体就是实现函数功能的代码
"""
练习1:定义一个函数,统计指定字符串中中文的个数
def count_chinese(str1):
"""
统计字符串中中文的个数
:param str1: 指定的字符串
:return: None
"""
count = 0
for x in str1:
if '\u4e00' <= x <= '\u9fa5':
count += 1
print(count)
练习2:定义一个函数,任意一个整数的阶乘
def factorial(num):
"""
求任意整数的阶乘
:param num: 需要求阶乘的数(必须是大于等于1的整数)
:return: None
"""
s = 1
for x in range(1, num+1):
s *= x
print(s)
练习3:定义一个函数,求任意一个圆的面积
def circle_area(r):
"""
求圆的面积
:param r: 圆的半径
:return: None
"""
print(3.1415926 * r ** 2)
4. 函数的调用
-
定义函数不会执行函数体,调用函数才会执行函数体
-
怎么调用函数
""" 语法: 函数名(实参列表) 说明: a.函数名 - 需要哪个函数的功能就调用哪个函数,就写哪个函数的函数名 (注意:函数名必须是已经定义好的函数的函数名) b.() - 固定写法 c.实参列表 - 以'数据1, 数据2, 数据3,...'的形式存在 实参就是通过形参从函数外部传递到函数内部具体的数据 (实参是用来给形参赋值) """
-
函数调用过程
""" 当代码指向到函数调用语句的时候: 第一步:先回到函数定义的位置 第二步:传参(用实参给形参赋值) 第三步:执行函数体 第四步:确定函数返回值 第五步:回到函数调用的位置接着往后执行 """
2. 函数的返回值
1. 返回值
"""
返回值就是从函数内部传递到函数外部的数据
1)怎么将确定函数返回值(怎么将指定的数据作为函数返回值)
看执行函数体的时候有没有遇到return,如果遇到return,return后面的值就是函数的返回值; 如果没有遇到return,返回值是None
2)怎么获取函数返回值
获取函数调用表达式的值就是获取函数的返回值。
(每个函数调用表达式都是有结果,结果是返回值;所以函数的返回值能做的事情,函数调用都可以做)
函数调用表达式:调用函数的语句
3)什么时候需要返回值
如果实现函数的功能产生了新的数据,我们就应该将新的数据返回
原因:每次调用函数的时候,系统会自动为这个函数创建一个临时的栈区域,用来保存在函数中产生的数据(形参也是保存在这个里面的),
当函数调用结束的时候系统会自动释放这块内存(内存中的数据会被删除),只有返回值不会直接删除
"""
def func3(n):
# n = 3; n = 4
if n % 2:
return 100
else:
return 200
x3 = func3(3)
print(f'x3:{x3}')
2. return
"""
return在函数中有两个作用:
1)返回返回值 - 谁在return的后面,谁就是返回值
2)提前结束函数 - 执行函数体的时候如果return,函数直接结束
"""
def func1():
print('======')
return
print('++++++')
print('hello world!')
x = func1()
print(x) # =========
3. 函数的参数
1. 位置参数和关键字参数
根据实参传递方式分类:
"""
1)位置参数: 以'实参1,实参2,实参3,...'的形式存在,通过位置一一对应的方式来给形参赋值
2)关键字参数:以'形参1=实参1, 形参2=实参2, ...'的形式存在,直接用=来确定实参和形参的对应关系
注意:位置参数和关键字参数可以混用,混用的时候位置参数必须在关键字参数的前面
"""
def func1(x, y, z):
# x=10, y=20, z=30
print(f'x:{x}, y:{y}, z:{z}')
func1(10, 20, 30) # x:10, y:20, z:30
func1(20, 10, 30) # x:20, y:10, z:30
func1(x=10, y=20, z=30) # x:10, y:20, z:30
func1(y=20, z=30, x=10) # x:10, y:20, z:30
func1(10, y=20, z=30) # x:10, y:20, z:30
func1(10, z=30, y=20) # x:10, y:20, z:30
func1(10, 20, z=30) # x:10, y:20, z:30
# func1(x=10, 20, 30) # 报错!
2. 参数默认值 - 形参
"""
定义函数的时候,可以通过 '形参名=值' 的方式给参数赋默认值; 如果一个形参有默认值,那么在调用函数的时候这个形参可以不用赋值。
注意:定义函数的时候,如果有的参数有默认值有的参数没有,那么没有默认值的参数必须放在有默认值参数的前面
"""
def func2(x=10, y=20, z=30):
print(f'x:{x}, y:{y}, z:{z}')
func2()
func2(100)
func2(100, 200)
func2(100, 200, 300)
func2(y=200, z=300)
def func3(x, z, y=20):
print(f'x:{x}, y:{y}, z:{z}')
3. 参数类型说明 - 定义函数的时候指定参数类型
"""
参数类型说明既可以提示使用者在调用函数的时候该传什么类型的数据;又可以让参数在函数体中使用的时候有代码提示。
1)方法1-没有默认值的参数: 形参名:类型名
2)方法2:给参数赋默认值,默认值的类型就是参数的类型
"""
def func4(str1: str, list1=[]) -> None:
str1.upper()
func4('anc', [1, 20])
# 补充:变量类型说明
message = '["abc", "sjksf", "23jhs"]'
list2 = eval(message) # type: list
list2.clear()
4. 不定长参数 - 解决参数个数不确定的问题
"""
1)带*的不定长参数
定义函数的时候,如果在某个形参前面加*,那么这个参数就变成了一个不定长参数,调用的时候这个形参可以接受若干个实参。
本质:如果形参有*,那么这个参数就会自动变成一个元组,它接收到的所有的实参会作为这个元组的元素
注意:a. 带*的不定长参数在传参的时候只能使用位置参数
b. 定长参数和带*的不定长参数混用的时候,*前的定长参数必须用位置参数传参,*后面的定长参数必须用关键字参数传参
2)带**的不定长参数 (了解)
本质:如果形参前有**,那么这个参数就会自动变成一个字典,它接收到的所有的实参会作为这个字典的键值对
注意:传参的时候只能用关键字参数传参
"""
def func5(*num):
print(f'num:{num}')
func5()
func5(10)
func5(20, 20)
func5(10, 20, 56, 78, 3)
def func6(x, *y):
pass
func6(10)
func6(10, 20, 34, 89)
练习: 定义一个函数,求多个数的和
def sum2(*nums):
s = 0
for x in nums:
s += x
return s
print(sum2(10, 29))
print(sum2(10, 29, 23))
print(sum2(10, 29, 23, 67, 23))