day 10 note 函数 进阶
01. 函数的参数
1. 位置参数和关键字参数
实参按照传递方式的不同分为位置参数和关键字参数两种
1. 位置参数
调用函数的时候让实参和形参一一对应(第一个实参给第一个形参赋值,第二个实参给第二个形参赋值…)
格式:数据1, 数据2, 数据3, …
2. 关键字参数
让实参和形参通过关键字(形参名)对应
格式:形参名1=数据1,形参名2=数据2,…
3. 关键参数和位置参数混用
混用的时候位置参数必须在关键字参数前面
def func1(x, y, z):
print(f'x:{x}, y:{y}, z:{z}')
(1) 位置参数
func1(10, 20, 30) # x:10, y:20, z:30
func1(10, 30, 20) # x:10, y:30, z:20
(2) 关键字参数
func1(x=100, y=200, z=300) # x:100, y:200, z:300
func1(z=30, x=10, y=20) # x:10, y:20, z:30
func1(x=100, y=200, y=300) #
func1(10, z=30, y=20) # x:10, y:20, z:30
func1(x=20, 40, z=60) # 抱错!位置参数必须在关键字参数的前面
print(10, end='a')
print(10, 20, 30, sep=',')
def print(*data, end='\n', sep=' '):
pass
sorted([1, 23, 8], reverse=True)
2. 参数默认值
定义函数的时候可以给以 ‘形参名=数据’ 的形式给参数赋默认值,调用函数的时候有默认值的参数可以不赋值
注意: 有默认值的参数必须在没有默认值参数的后面
def func2(x=1, y=10, z=100):
print(f'x:{x}, y:{y}, z:{z}')
func2(1, 2, 3) # x:1, y:2, z:3
func2(10, 20) # x:10, y:20, z:100
func2(10)
func2()
func2(y=200)
func2(z=300)
def func3(x, y, z=100):
print(f'x:{x}, y:{y}, z:{z}')
3.参数类型说明
定义函数的时候,可以对参数类型进行说明
1) 赋默认值,默认值是什么类型,参数类型说明就是什么类型
2) 形参名:数据类型
def func4(x=''):
pass
def func5(x: list) -> None:
x.append('100')
func5([])
4. 不定长参数
在形参前加*或者加**,就可以让这个参数变成不定长参数。不定长参数的形参可以同时接受多个实参
1)带 * 的不定长参数
带 * 的参数会变成一个元组,元组中的元素就是对应的实参
注意:a. 一个函数可以同时存在带和不带的参数,如果不带的在带的后面,不带的参数必须使用关键字参数
b.带的参数必须使用位置参数
2)带 ** 的不定长参数
带**的不定长参数会变成一个字典;调用的时候用关键字参数传参,每个关键字就是字典的key,关键字后面的数据就是字典的value
注意:a.定义的时候定长参数必须放在**不定长参数的前面
b.带 * 和带 ** 的不定长参数可以同时存在,但 星 是必须在 星星 前面。(如果同时存在可以让函数在调用的时候更加灵活)
def func6(*x):
print(f'x:{x}')
func6()
func6(10)
func6(10, 20)
func6(1, 2, 3, 4, 5)
练习:定义一个函数,可以求多个数的和
sum1(10, 20) sum1(10, 20, 30)
def sum1(*num):
s = 0
for x in num:
s += x
print(s)
sum1(10, 20) # 30
sum1(10, 20, 30) # 60
def func7(x, *y):
print(f'x:{x}, y:{y}')
func7(10) # x:10, y:()
func7(10, 20, 30, 40, 50) # x:10, y:(20, 30, 40, 50)
def func8(*x, y):
print(f'x:{x}, y:{y}')
func8(1, 2, 3, y=10)
def func9(**num):
print(num)
func9() # { }
func9(a=10, b=20) # {'a': 10, 'b': 20}
func9(x=100, y=200, z=300, m=0) # {'x': 100, 'y': 200, 'z': 300, 'm': 0}
def func10(x, **y):
print(f'x:{x}, y:{y}')
func10(10, a=20, c=30, d=40) # x:10, y:{'a': 20, 'c': 30, 'd': 40}
func10(a=1, b=2, c=3, x=100) # x:100, y:{'a': 1, 'b': 2, 'c': 3}
def func11(*x, y):
pass
def func12(*x, **y):
print(f'x:{x}, y:{y}')
func12(1, 2, 3)
func12(a=10, b=20)
func12(1, 2, a=3, b=4)
02. 函数的返回值
1. 返回值
1)什么是返回值
返回值就是从函数内部传递到函数外部的数据。(如果实现函数的功能,产生了新的数据一般都需要将这个新的数据通过返回值返回)
2)怎么确定函数返回值
在函数体中通过return关键字来返回返回值: return 数据
注意:同一个函数中,只有一个return有效。(因为执行函数体的时候只要遇到return函数直接结束)
如果要在一个函数中返回多个数据,用能够保持多个数据的容器。常用元组: return 数据1, 数据2, 数据3,…
3)怎么在函数外部获取函数返回值
获取函数调用表达式的值就是获取函数的返回值。(返回值对应的数据能做的,函数调用表达式都可以做)
def sum1(num1, num2):
s = num2 + num1
return s, s/2
def func1():
print('111111')
return # 相当于 return None
print('222222')
func1()
def func2():
return 100
def func3(x):
print(x)
print(100)
print(func2())
a = 100
b = func2()
print(a, b)
print(100 + 200)
print(func2() + 200)
list1 = [100, func2()]
print(list1)
func3(100)
func3(func2())
def func4():
return [1, 2, 3]
print(func4())
print(func4()[0])
for x in func4():
print(f'x: {x}')
if func4():
print('你好!')
def func5(x):
if x & 1:
return '奇数'
else:
return '偶数'
print(func5(11))
def func6():
print('abc')
print(func6())
练习:删除指定列表中所有指定元素
[1, 23, 4, 5, 1, 34, 2, 1] 删除元素 1 -> [23, 4, 5, 34, 2]
方法一:
def del_item(list1: list, item):
for x in list1[:]:
if x == item:
list1.remove(x)
nums = [1, 23, 4, 5, 1, 34, 2, 1]
del_item(nums, 1)
print(nums)
方法二:
def del_item2(list1: list, item):
new_list = [x for x in list1 if x != item]
return new_list
nums = [1, 23, 4, 5, 1, 34, 2, 1]
new_l = del_item2(nums, 1)
new_l.append('end')
print(new_l)
03. 全局变量和局部变量
根据变量的 作用域 不同将变量分为全局变量和局部变量两种
1. 全局变量
定义在函数和类外面的变量都是全局变量
全局变量的 作用域:从定义开始到程序结束的任何地方都可以用
print(’=全局变量==’)
a = 10 # a是全局变量
for b in range(4): # b是全局变量
c = 100 # c是全局变量
pass
for _ in range(3):
print(f'循环里面a: {a}')
print(f'循环里面b: {b}')
print(f'循环里面c: {c}')
def func1():
print(f'函数里面a:{a}')
print(f'函数里面b:{b}')
print(f'函数里面c:{c}')
func1()
print(f'外部a:{a}')
print(f'外部b:{b}')
print(f'外部c:{c}')
2. 局部变量
定义在函数里面的变量是局部变量
作用域:从定义开始到函数结束
局部变量产生的原因:每次调用函数的时候,系统会自动为被调用的这个函数在栈区间开辟一块独立的内存空间,专门用来保存在这个函数中定义的变量。当函数调用结束的时候这块内存空间会自动销毁。
print(’=局部变量==’)
def func3(m=10): # m 是局部变量
x = 'abc' # x 是局部变量
print(f'函数内部x:{x}')
print(f'函数内部m:{m}')
for _ in range(2):
print(f'函数内部x2:{x}')
func3()
print(f'函数外部x:{x}') # NameError: name 'x' is not defined
print(f'函数外部m:{m}') # NameError: name 'm' is not defined
3. global 和 nonlocal
global 和 nonlocal是函数体中的关键字,只能在函数体中使用
1) global
global的作用:在函数中定义或者修改全局变量
用法:
global 变量名
变量名 = 值
2) nonlocal
作用:在局部的局部中修改一个局部变量的值
nonlocal 变量名
变量名 = 值
1) 使用global在函数中定义全局变量
def func4():
global z
z = 100
func4()
print(f'外部z:{z}')
2) 修改全局变量的值 (如果直接在函数内容给全局变量赋值,不会修改值,而是产生一个新的局部变量)
name = '张三'
def func5():
global name
name = '李四'
print(f'函数内部name: {name}')
func5()
print(f'函数外部name: {name}')
def func6():
age = 18
def func7():
nonlocal age
age = 20
print(f'局部的局部age: {age}')
func7()
print(f'局部age:{age}')
04. 匿名函数
1. 什么是匿名函数
匿名函数的本质还是函数;但是匿名函数只能通过一条语句来实现函数的功能。
1)语法:
函数名 = lambda 形参列表:返回值
相当于:
def 函数名(形参列表):
return 返回值
求两个数的和
def sum1(num1, num2):
return num1 + num2
sum1 = lambda num1, num2=3: num1+num2
print(sum1(10, 20))
print(sum1(num2=100, num1=200))
print(sum1(2))
写一个匿名函数func2, 功能是打印一个数的平方
func2 = lambda num: print(num**2)
print(func2(3))
func2(3)
练习:写一个匿名函数,返回指定的年是否是闰年
is_leap_year = lambda year: (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
print(is_leap_year(2020))
is_leap_year2 = lambda year: '闰年' if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) else '平年'
print(is_leap_year2(2021))