01 认识函数
导引
求1+2+3+…+100的和
sum1 = 0
for i in range(1, 101):
sum1 += i
print(sum1)
# 使用函数sum()
print(sum(range(1, 101)))
求nums中最大的值
nums = [56, 88, 78, 53, 44]
max1 = 0
for i in nums:
if i > max1:
max1 = i
print(max1)
# 使用函数max()
print(max(nums))
1. 函数的作用:
- 写程序的时候会出现这样的情况,有一个功能需要在多个地方使用,如果没有函数需要在每次使用这个功能的时候把实现这个功能的代码写一遍;
- 如果有函数可以提前将实现指定功能的代码封装成函数,然后在所有需要这个功能的位置调用这个函数
2. 认识函数
概念: a. 函数就是实现某一特定功能的代码的封装。
b.函数就是将实现某一个功能的所有代码打成一个包(封装起来),那以后在需要这段代码对应的功能的时候就不需要重复写这段代码了,而是直接调用这段代码的函数。
def sum1(n):
s = 0
for i in range(1, n+1):
s += i
print(s)
# 1+2+3...+100
sum1(100)
3. 函数的分类
根据函数由谁创建的可以将函数分为: 系统函数和自定义函数
1) 系统函数: 由系统创建好的函数(print、input、type、chr、ord、max、sum等)
2) 自定义函数: 由程序员自己创建的函数
4. 定义函数(创建函数)
1) 语法:
def 函数名(形参列表):
函数说明文档
函数体
2) 说明:
说明 | |
---|---|
函数名 | 名字由程序员自己决定 两个要求: 是标识符; 不能是关键字 三个规范: 见名知义(看到函数名就大概知道这个函数的功能是什么); 字母都小写且多个单词之间使用下划线隔开; 不使用系统函数名、类名或者模块名。 |
() | 固定写法 |
形参列表 | a. 以’变量名1, 变量名2, 变量名3,…'的形式存在,这儿的每一个变量就对应一个形参(形参可以没有,也可以有多个); b. 形参可以将函数外部的数据传递到函数的内部; c. 定义函数的时候需不需要形参需要几个形参,就看实现函数的功能的时候需不需要额外的数据需要几个额外的数据。 |
函数说明文档 | 本质就是和def保持一个缩进的多行注释 |
函数体 | 结构上就是和def保持一个缩进的一条或者多条语句(至少一条); 逻辑上函数体就是实现函数功能的代码,即封装的对象。 |
补充:初学者定义函数的步骤:
1.确定函数功能
2.确定函数名(根据功能)
3.确定形参列表(看实现函数的功能的时候需不需要额外的数据需要几个额外的数据。)
4.使用函数体实现函数功能(实现函数的功能的时候,需要将形参当成对应的数据来使用)
案例
案例1: 定义一个函数: 求任意两个数的和
def sum2(num1, num2):
"""
(功能说明)求和两个数的和
:param num1:数字1(参数说明)
:param num2:数字2
:return:(返回值说明)None
"""
print(num1 + num2)
案例2:定义一个函数: 统计任意一个列表中数字的个数
def count_num(list1):
count = 0
for i in list1:
# if type(i) in (int, float)
if type(i) == int or type(i) == float:
count += 1
print(count)
list2 = ['ashdif', 23, 2.3, True, {1, 2}, 100]
count_num(list2)
练习
练习1: 定义一个求10的阶层
def factorial(n):
result = 1
for i in range(1, n+1):
result *= i
print(result)
练习2:统计任意一个字符串中中文的数量
def count_Chinese(str1):
count_num = 0
for i in str1:
if '\u4e00' <= i <= '\u9fa5':
count_num += 1
print(count_num)
练习3:定义一个函数判断一个字符串是否以另外一个字符串开头
def str_start(str1, str2):
print(str1[:len(str2)] == str2)
练习4:定义一个函数,将一个名字列表中所有的名字按照123重复报数的方式分成三组
def list_name(namelist):
list1 = namelist[0::3]
list2 = namelist[1::3]
list3 = namelist[2::3]
print(list1, list2, list3)
names = ['路飞', '娜美', '乌索布', '索罗', '山治', '乔巴', '纳兹', '鸣人', '佐助', '小樱', '卡卡西', '好色仙人','犬夜叉', '杀生丸', '戈薇', '玲', '奈落', '邪见']
list_name(names)
02 调用函数
1.调用函数 - 使用机器
定义函数的时候不会执行函数体,调用函数的时候才会执行函数体(调用多少次执行多少次)
- 语法:
函数名(实参列表)
- 说明:
| | 说明 |
| :------- | :----------------------------------------------------------- |
| 函数名 | 可以是任何已经定义过的函数的函数名 |
| () | 固定写法 |
| 实参列表 | a. 以"数据1, 数据2, 数据3,…"的形式存在,这儿的每一个数据就是一个实参。
b. 实参是用来给形参赋值的(实参才是真正从函数外部传递到函数内部的数据),实参必须与形参一一对应。 |
def func1():
#print(10 + 'a ' )
print('======')
print('------')
print('++++++')
func1()
def func2(x, y, z):
print(x, y, z)
func2(10, 20, 30)
2.函数调用过程
第一步: 回到函数定义的位置
第二步: 传参(用实参给形参赋值)
第三步: 执行函数体
第四步: 确定函数返回值
第五步: 回到函数调用的位置,接着往后执行
def sum2(num1, num2):
print(num1 + num2)
sum2(100, 200)
03 函数的参数
1.位置参数和关键字参数 - 根据调用函数的时候实参的提供方式不同来分类的
1) 位置参数: 以’数据1, 数据2, 数据3,…'形式存在,通过位置来和形参一一对应
2) 关键字参数: 以’形参1=数据1, 形参2=数据2, 形参3=数据3,…'形式存在(交换关键字参数的顺序不影响结果)
def func1(a, b, c):
print(f'a:{a}, b:{b}, c:{c}')
# 位置参数
func1(10, 20, 30) # a:10, b:20, c:30
func1(20, 10, 30) # a:20, b:10, c:30
# 关键字参数
func1(a=100, b=200, c=300)
func1(b=200, a=100, c=300)
注意:
a. 位置参数和关键字参数可以一起使用,但是位置参数必须放在关键字参数的前面
b. 不管以什么样的形式传参,都必须保证每个参数都有值
func1(100, b=200, c=300)
func1(100, c=300, b=200)
# func1(100, a=200, c=300) 报错!a赋值两遍且b没有被赋值
# func1(a=100, 200, c=300) 报错!位置参数必须在关键字参数前面!
2.参数默认值
在定义函数的时候,可以以’形参名=数据’的方式给参数赋默认值;
如果参数有默认值,调用函数的时候有默认值的参数可以不用传参。
def func2(a=1, b=2, c=3):
print(f'a:{a}, b:{b}, c:{c}')
func2() # a:1, b:2, c:3
func2(10) # a:10, b:2, c:3
func2(10, 20) # a:10, b:20, c:3
func2(10, 20, 30) # a:10, b:20, c:30
func2(c=300) # a:1, b:2, c:300
注意: 定义函数的时候如果有的参数有默认值有的没有,没有默认值的参数必须在有默认值参数的前面。
def func3(a, b=2, c=3):
print(f'a:{a}, b:{b}, c:{c}')
案例: 定义一个函数为10的阶乘
def factorial(num=10):
s = 1
for i in range(1, num+1):
s *= i
print(s)
factorial() # 3628800
factorial(5) # 120
3.参数类型说明 - 可以让形参在函数体中使用的时候有相关的代码提示
1) 没有默认值的参数直接在参数名后加’: 类型名’
2) 有默认值的参数默认值的类型就是说明的类型
def func4(a:list, b='abc'):
pass
list1 = [
{'a': 10, 'b': 20},
{'a': 100, 'b': 'abc'}
]
补充: 通过类型注释对变量进行类型说明
c = list1[-1]['b'] # type: str
print(c) # 'abc'
4.不定长参数(了解) - 参数个数不确定
1) 带*的不定长参数:
a. 在定义函数的时候,在某个参数前加*,就可以让这个参数同时接受多个实参。
b. 带*的不定长参数的本质是一个元组,它接收到的所有的实参都会成为这个元组的元素。
案例: 定义一个函数,求多个数的和
def sum1(*nums):
result = 0
for i in nums:
result += i
print(result)
sum1() # 0
sum1(10, 20) # 30
def student_info(name, age, *score):
print(name, age, *score)
student_info('小明', 18, 89) # 小明 18 89
student_info('小花', 18, 90, 89, 46) # 小花 18 90 89 46
注意:
a. 带*的不定长参数只能用位置参数传参
def func5(a, *b):
pass
func5(10, 20, 30)
b. 带*前面的不定长参数只能用位置参数传参
def func6(x, y, *num):
print(x, y, num)
func6(10, 20, 67, 64, 56) # 10 20 (67, 64, 56)
c. 带*后面的不定长参数只能用关键字参数传参
def func7(*num, x, y):
print(num, x, y)
func7(10, 20, 30, x=40, y=50) # (10, 20, 30) 40 50
def func8(a, b, *num, x, y):
pass
d. 形参列表中如果单独出现一个*,它的目的只是想要在调用这个函数的时候*后面的参数必须使用关键字参数,*前面的参数必须使用位置参数。
def func9(a, *, b):
pass
2) 带**的不定长参数
定义函数的时候在某个参数前加 ** ,就可以让这个参数同时接收多个实参(只能是关键字参数)。
带**的不定长参数的本质是一个字典,它接收到的所有的关键字参数会成为这个字典的元素。
def func10(**x):
print(x)
func10() # {}
func10(a=10) # {'a': 10}
func10(a=10, b=20, c=30) # {'a': 10, 'b': 20, 'c': 30}
func10(c=90, m=100, e=87, h=56) # {'c': 90, 'm': 100, 'e': 87, 'h': 56}
*args, **kwargs 存在的目的是为了让这个函数在调用的时候可以足够灵活(既可以使用不定个数位置参数,也可以使用不定个数关键字参数,位置参数和关键字参数还可以一起使用)
def func11(*args, **kwargs):
print(args, kwargs)
func11(10, 20) # (10, 20) {}
func11(10, 20, 30, 40) # (10, 20, 30, 40) {}
func11(k=100, t=200) # () {'k': 100, 't': 200}
func11(10, 20, a=10, b=30, c=40) # (10, 20) {'a': 10, 'b': 30, 'c': 40}
04 函数的返回值
1.什么是返回值
返回值就是从函数内部传递到函数外部的数据(每次函数只能传一个数据到函数外部)
1)在函数内部怎么确定函数返回值
-
return后面的值就是函数的返回值
-
在函数体实现函数功能的时候,可以在任何你需要的地方(一般在最后)通过return关键字,将需要传递到函数外部的数据作为返回值返回
-
return使用方法: return 需要返回的数据
注意:
- return除了返回数据,还会提前结束函数(执行函数体的时候只要遇到return整个函数直接结束)
- 如果执行函数体的时候没有遇到return,这个函数的返回值就是None
案例: 定义函数求任意两个数的和
def sum2(num1, num2):
return num1+num2
return会提前结束函数
def func1():
print('=====')
return None
print('-----')
print('!!!!!!')
func1()
案例: 定义函数求任意两个数的和以及乘积
def sum2(num1, num2):
return num1 + num2, num1 * num2
print(sum2(20, 30))
2)在函数外部怎么使用函数返回值
- 使用函数调用表达式的值就是使用函数的返回值(函数调用表达式有结果,这个结果就是这次调用函数的时候获得的返回值)
- 返回的值能做的,函数调用表达式都可以做
print(sum2(100, 200)) # (300, 20000)
a = 300
b = sum2(100, 200)
print(a, b) # 300 (300, 20000)
list1 = [300, sum2(100, 200)]
print(list1) # [300, (300, 20000)]
print(sum2(100, 200) * 3) # (300, 20000, 300, 20000, 300, 20000)
def func2():
return 'abc'
print(func2()[-1]) # 'abc'[-1] -> 'c'
print(func2().upper()) # ABC
05 变量作用域
根据变量作用(可使用范围)不同,可以将变量分为全局变量和局部变量两种
1. 全局变量
全局变量指的是没有定义在函数或者类中的变量。
全局变量的作用域是从定义开始到程序结束。
a = 10
print(f'在外面使用a:{a}')
for i in range(3):
print(f'在循环中使用a:{a}')
def func1():
print(f'在函数中使用a:{a}')
func1()
# i和b都是全局变量
for i in range(3):
b = 20
print(f'循环中使用i和b:{i}, {b}')
print(f'循环外面使用i和b:{i}, {b}')
def func2():
print(f'函数中使用i和b:{i}, {b}')
func2()
2. 局部变量
定义在函数中的变量就是局部变量,局部变量的作用域是从定义开始到函数结束。(形参是局部变量)
# m和n都是局部变量
def func3(m):
n = 100
print(f'在函数里面使用m和n:{m}, {n}')
func3(5)
# print(f'在函数外面使用m和n:{m}, {n}') # 报错
3.关键字global
如果想要在函数里面定义一个全局变量或者修改一个全局变量的值,需要在函数中使用这个变量前加global进行说明。
num = 19
def func4():
global num
num = 20
print(f'函数内部:{num}')
global name
name = input('请输入: ')
func4()
print(f'函数外部:{num}')
print(f'函数外部:{name}')