函数
函数的作用
没有函数的问题:
1)同样的功能需要多次的时候,需要把实现这个功能的代码写多遍
2)需求发生改变,可能涉及到多个位置代码的改变
“”"
1.什么是函数
1)函数的概念
函数就是实现某一特定功能的一段代码
2)函数的分类
系统函数:系统已经定义号的函数,程序员根据需求直接使用。
自定义函数:程序员自己定义的函数。
2.定义函数
语法:
def 函数名(形参列表):
函数说明文档
函数体
说明:
1.def - 关键值;固定写法
2.函数名 - 程序员自己命名;
要求:标识符;不能是关键值
规范:所有字母都小写,多个单词之间用下滑线隔开
见名知义(看到函数名能够大概知道函数的功能)
不能使用系统自带的函数命、模块名和类名
3.形参列表 - 以 变量1,变量2,变量3,.....的形式存在(可以一个变量都没有)
形参的作用是将函数外部的数据传递到函数的内部
定义函数的时候的形参数有没有或者有几个参数,需要看函数的功能
4.函数说明文档 - 就是用""""""表示说明的文字(相当于机器的说明书)
5.函数体 - 和def保持一个缩进的一条或者多条语句;就是实现函数功能的一条或者多条语句
(重要!!!)注意:定义函数的时候不会执行函数体!!!调用函数的时候才会执行函数体
3.初学者定义函数的步骤
**第一步:**确定函数的功能
**第二步:**根据函数的功能,确定函数的名字
**第三步:**确定函数的参数(看函数功能需不需要几个额外的参数,需要几个)
**第四步:**实现函数的功能
**第五步:**写函数的说明文档
def sum_two(x, y):
"""
求两个数的和(函数的功能说明)
:param x: 需要求和的第一个数(对参数的说明)
:param y: 需要求和的第二个数(对参数的说明)
:return: None(返回值说明)
"""
print(x + y)
练习:定义一个函数定义一个函数的阶乘(factorial)
def factorial(n):
"""
计算n的阶乘
:param n: 输入的需要计算阶乘的数字
:return: None
"""
sum = 1
for i in range(1, n + 1):
sum *= i
print(sum)
4.调用函数
语法:
函数名(实参列表)
说明:
函数名 - 已经定义好的函数的函数名
实参列表 - 以数据1,数据2,数据3,....的形式存在(也可以没有)
真正传递到函数中使用的数据
函数的参数
1.位置参数和关键字参数(实参)
根据函数调用的时候实参的传递方式将实参分为位置参数****和关键字参数
1)位置参数 - 调用函数的时候直接在括号里面写多个实参,实参和形参是一一对应的。
2)关键字参数 - 调用函数的时候以 形参名=实参 的形式来确定实参。(位置不影响结果)
注意: 位置参数和关键字参数可以一起使用,但是位置参数必须在关键字参数的前面
不管以什么样的形式传参,最终都要保证每个参数都有值
“”"
def func1(a, b, c):
print(f'a:{a}, b:{b}, c:{c}')
位置参数
func1(20, 30, 40) # a:20, b:30, c:40
func1(30, 20, 40) # a:30, b:20, c:40
关键参数
func1(a=100, b=200, c=300) # a:100, b:200, c:300
func1(b=200, c=300, a=100) # a:100, b:200, c:300
关键参数不能重复
# func1(a=100, b=200, a=300, c=400) # SyntaxError: keyword argument repeated
每次形参都必须赋值
# func1(a=100, c=300) # TypeError: func1() missing 1 required positional argument: 'b'
位置参数和关键字参数一起用
func1(10, c=30, b=20) # a:10, b:20, c:30
func1(100, 200, c=300) # a:100, b:200, c:300
位置参数必须在关键字参数的前面
# func1(a=10, 20, c=30) # SyntaxError: positional argument follows keyword argument
2.参数默认值(形参)
在定义函数的时候,可以给形参赋默认值; 如果一个形参有默认值,那么这个参数在调用的时候可以不用传参。
如果定义函数的时候有的参数有默认值,有的参数没有默认值;没有默认值的参数必须在有默认值的参数的前面。
def func2(a=10, b=20, c=30):
print(f'a:{a}, b:{b}, c:{c}')
func2() # a:10, b:20, c:30
func2(100) # a:100, b:20, c:30
func2(100, 200) # a:100, b:200, c:30
func1(100, 200, 300) # a:100, b:200, c:300
func2(c=300) # a:10, b:20, c:300
func2(100, c=300) # a:100, b:20, c:300
# SyntaxError: non-default argument follows default argument
# def func3(a=10, b, c=30):
# pass
def func4(b, a=10, c=30):
pass
func4(30)
func2(b=40)
3.不定长参数(参数个数不确定)
1) 定义函数的时候在一个参数前加 * , 那么这个参数就是一个不定长参数,可以同时接收多个实参。
注意: a.带*的参数的本质就是一个元组;
b.在调用的时候这个参数必须使用位置参数传参
2) 定义函数的时候在一个参数前加 ** ,那么这个参数就是一个不定长参数,可以同时接收多个实参。
注意:a.带 ** 的参数的本质是一个字典
b.在调用的是这个参数必须使用关键字参数传参(关键自己随便命名)
练习:定义一个函数求多个数的和
def sum1(*nums):
# nums就是一个元组
total = 0
for x in nums:
total += x
print(total)
sum1() # nums=()
sum1(10) # nums=(10,)
sum1(10, 20) # nums=(10, 20)
sum1(10, 20, 40, 6, 2, 89) # nums=(10, 20, 40, 6, 2, 89)
定义一个函数计算一个学生所有学到的总成绩
def total_score(name, *scores):
print(name)
print(scores)
total_score('小明')
total_score('小明', 29, 89, 78)
def func5(**num):
print(num)
func5() # num={}
func5(a=10, b=30) # num={'a': 10, 'b': 30}
func5(name='小明', age=18, sex='男') # num{'name': '小明', 'age': 18, 'sex': '男'}
面试题: 定义函数的时候经常看到函数的参数 : *args,
**kwargs, 问题:这样写的意义和目的是什么?
两种不定长参数一起用,最终还是实现一个参数个数不定的函数;只是这个函数在调用的时候更加灵活,既可以用位置参数传参也可以用关键字参数传参,还可以位置参数和关键字参数一起用
def func6(*args, **kwargs):
print(args, kwargs)
func6()
func6(1, 2, 3)
func6(a=2, b=3)
func6(1, 2, a=2, b=3)
4.参数类型说明
def func7(a: int, b=10): #参数类型说明并没有把参数的类型就固定了,而是提示应该给虚参传输的类型值
print(a,b)
func7(10, 20)
func7('abc', 'hu')
func7([1, 2], 100)
def func8(list1: list, str1=''):
pass
函数的返回值
1.什么是返回值=
1)概念
返回值就是从函数内部传递到函数外部的数据;
返回值就是return关键字后面的表达式的值;
返回值就是函数调用表达式的值。
2)return关键字
return是只能在函数体中使用的关键字,作用有两个:
a. 确定函数的返回值(return后面是什么,函数的返回值就是什么)
b. 提前结束函数(只要遇到return,整个函数直接结束)
注意: 如果在执行函数的时候没有遇到return, 那么函数的返回值是 None
3)函数调用表达式
调用函数的表达式就是函数调用表达式;当函数调用结束后,函数调用表达式的值就是函数的返回值。
2. 怎么确定函数是否需要返回值:
看实现函数的功能会不会产生新的数据,如果有就将这个新的数据作为返回值返回
练习:定义函数获取指定字符串中所有的数字字符
def get_num(str1):
num_str = ''
for x in str1:
if '0' <= x <= '9':
num_str += x
return num_str
#用变量保存函数调用表达式的值,其实就是保存函数的返回值
re = get_num('asd2kshjd928jsj78==2')
print(re)
print(int(re)*100)
list1 = [re, 100]
print(list1)
返回值对应的数据能做的事情,函数调用表达式都可以做
def sum1(a: int, b: int):
return a+b
print(30)
print(sum1(10, 20))
num1 = 30
num2 = sum1(10, 20)
print(30+1)
print(sum1(10, 20)+1)
list2 = [30, sum1(10, 20)]
print(list2)
def create_list():
return [1, 2]
print([1, 2][-1]) #2
print(create_list()[-1]) #2
if [1, 2]:
print('执行语句!') #执行语句!
if create_list():
print('执行语句!') #执行语句!
a = max([1, 2, 78, 9, 8])
print(a)
print(min([23, 45, 5]))
a = print('abc')
print(a) # None
nums = [1, 23, 56, 7]
print(nums.append(100)) # None
print(nums)
3.函数调用过程(执行过程)(重要!!!)
第一步: 回到函数定义的位置
第二步: 传参(用实参给形参赋值;传参的时候必须保证每个参数都有)
第三步: 执行函数体
第四步: 执行完函数体确定返回值
执行完函数体:a. 执行到函数体的最后 b. 遇到return
怎么确定返回值: 看函数执行完成的时候有没有遇到return,如果遇到了返回值就是return后面的值;
没有遇到return返回值是None
第五步: 回到函数调用的位置接着往后执行(这个时候函数调用表达式的值就是函数的返回值)
4.多个返回值
函数的返回值永远都只有一个,如果要同时返回多个数据,就返回一个容器。常用元组
如果一个函数要同时返回多个,将多个数据作为一个元组中的元素返回
def func1(a):
return a**2, 2*a
print(func1(10)) # (100, 20)
re = func1(4)
print(re[0], re[1]) # 16 8
x, y = func1(5)
print(x, y) # 25 10
变量的作用域
变量的作用域指的是变量的使用范围,根据变量使用范围,我们将变量分为全局变量和局部变量两种:
1.全局变量和局部变量
1)全局变量
定义在函数和类的外部的变量就是全局变量。
作用域: 从定义开始到文件结束的任何位置都能使用
2)局部变量
定义在函数中的变量就是局部变量
作用域: 从定义开始到函数结束的任何位置都能使用
# ===============全局变量===============
# a是全局变量
a = 10
# x是全局变量
for x in range(4):
# y是全局变量
y = 10
pass
print('函数外:', a, x, y)
def func1():
print('函数里面:', a, x, y)
func1()
# ===============局部变量===============
# x1, y1, a1都是局部变量
def func2(x1, y1):
a1 = 10
print('函数内部:', x1, y1, a1)
func2(100, 200)
# print('函数外部:', x1, y1, a1) # 报错!
2.global和nonlocal
global和nonlocal只能在函数体中使用
global: 用global可以在函数里面定一个全局变量。
nonlocal: 在局部的局部中修改局部变量的值的时候使用
# 全局name
name = '小明'
age = 18
def show_message():
name = '小花' # 局部变量name
print(name) # 小花
# print(age) # 用global声明的变量只能在声明以后使用
global age
age = 20
print(age) # 20
global sex
sex = 'boy'
show_message()
print(name) # 小明
print(age) # 20
print(sex) # boy
def func3():
num = 100
def func4():
num = 200
print('函数中的函数:', num) #200
func4()
print('当前函数:', num) #100,如果func4中的num的类型申请位nonlocal类型,那此处的输出应该也为200
func3()
练习: 有一个银行账号,定义两个函数对这个账号进行存钱和取钱的操作。调用函数进行多次存钱和取钱操作以后打印账号的余额。
account = {
'name': '余婷',
'id': '728282292989',
'tel': '162627223332',
'balance': 50000.00
}
num = 50000.00
def save(money: int):
# account['balance'] += money
global num
num += money
def get(money: int):
# if account['balance'] < money:
# print('余额不足')
# else:
# account['balance'] -= money
global num
if num < money:
print('余额不足')
else:
num -= money
print(account['balance']) # 50000.0
save(100)
get(2000)
get(20000)
get(20000)
get(20000) # 余额不足
print(num) # 8100.0
# print(account['balance'])
匿名函数
1.匿名函数
匿名函数的本质还是函数,除了定义的语法以外,其他的和普通函数没有区别。
语法:
函数名 = lambda 参数列表:返回值
相当于:
def 函数名(参数列表):
return 返回值
写一个匿名函数求两个数的和:
sum1 = lambda num1, num2=6: num1+num2
# def sum1(num1, num2):
# return num1 + num2
print(sum1(10, 20))
print(sum1(num1=100, num2=200))
print(sum1(4))
练习: 写一个匿名函数根据年龄的范围返回’成年’、‘未成年’
# 包含了一个条件表达式
is_adult = lambda age: '成年' if age >= 18 else '未成年'
print(is_adult(8))
is_adult = lambda age: age >= 18