一、 函数的参数
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: str, 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])
print(create_list()[-1])
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))
re = func1(4)
print(re[0], re[1])
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)
global sex
sex = 'boy'
show_message()
print(name)
print(age)
print(sex)
def func3():
num = 100
def func4():
num = 200
print('函数中的函数:', num)
func4()
print('当前函数:', num)
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'])
save(100)
get(2000)
get(20000)
get(20000)
get(20000)
print(num)
四、 匿名函数
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