Day10 函数
-
函数的参数
-
未知参数和关键字参数
-
根据实参的提供是不同将实参分为位置参数和关键字参数
-
位置参数: 调用函数时, 让实参和形参在位置上一一对应
-
关键字参数: 调用函数的时候以’形参名=值’的形式确定形参对应的实参
-
位置参数和关键字参数混用: 位置参数必须在关键参数前面, 同事必须保证每个参数都会有一次赋值
# 位置参数 func1(10, 20, 30) # 关键字参数 func1(x=10, y=20, z=30) func1(z=30, x=10, y=20) # 混用 func1(10, 20, z=30) func1(10, z=30, y=20) # func1(x=10, 20, z=30) #SyntaxError: positional argument follows keyword argument
-
-
参数默认值
-
定义函数的时候可以直接在形参后面用=给形参赋默认值
-
有默认值的参数调用的时候可以不用传参
-
如果有的参数有默认值,有默认值的参数必须放于没有默认值参数的后面
def func2(x=10, y=20, z=30): print(f'x:{x}, y:{y}, z:{z}') func2() func2(100) func2(z=300) def fun3(z, x=10, y=20): print(f'x:{x}, y:{y}, z:{z}') fun3(100) fun3(z='asdzdasad')
-
-
参数类型说明
-
无默认参数的类型说明 - :类型名
-
有默认值的参数, 默认值的类型就是参数对应的类型
def func4(x: str, y=''): x.split('\n') y.replace('you', 'me')
-
-
不定长参数
-
带* 的不定长参数: 在某个形参前加*, name这个形参就是一个不定长参数, 他可以接受任意多个实参
-
带*的参数本质就是一个元组, 对应的实参是元组中的元素
-
带 * * 的不定长参数: 在某个形参前加**, name这个形参就是一个不定长参数, 它可以接受任意多个实参;
-
带**的参数本质就是一个字典, 对应的关键字参数就是字典中的键值对
-
注意: **的不定长参数对应的实参必须使用关键字参数传参
def func5(*x): print(x) func5() func5(10) func5(19, 2, 4, 5, 6)
-
定长参数在*的不定长参数前, 定长和不定长都使用位置参数传参
def func6(char, *nums): print(f'char:{char}, nums:{nums}') func6('+') func6('+',10, 20, 30) #char:+, nums:(10, 20, 30)
-
定长参数在*的不定长参数后, 定长参数必须使用关键字参数传参
def func7(*nums, char): print(f'nums:{nums}, char:{char}') func7(10, 20, char='*') def func8(*, a, b, c): print(f'a:{a}, b:{b}, c{c}') func8(a=10, b=20, c=30)
-
** 的使用
def func9(**x): print(x) func9() func9(x = 10) func9(m=1, n=2, a=3, b=100)
-
定长参数再**的不定长前, 定长既可以用位置参数也可以用关键字参数
def func10(x, **y): print(f'x:{x}, y:{y}') func10(10, a=10, b=20) func10(x=100, m=1, n=2)
-
定长参数不能放在**对应的不定长参数后面
# def func11(**x, y): # pass
-
带* 的不定长参数和带 * * 的不定长参数可以一起使用, 带*的必须放在带**的前面
def func11(*args, **kwargs): pass
-
-
-
-
函数的返回值
-
返回值
- 返回值的作用就是将函数内部的数据传递到函数外
-
怎么确定函数返回值 - 怎么将函数内部的数据传递到外部
- 在函数体中用return来返回返回值(一个函数只有一个返回值)
- 什么时候需要返回值: 如果函数的功能产生了新的数据, 将新的数据都返回.
-
怎么获取函数返回值
-
获取函数调用表达式的值就是获取返回值
-
函数调用表达式 - 调用函数的语句
-
函数调用表达式的值就是函数返回值, 函数返回值能做的事情, 函数调用表达式都能做
def sum2(num1, num2): return num1 + num2 sum2(10, 20) def func1(): return 100 print(100) print(func1()) a = 100 b = func1() print(a, b) a = 100 + 200 b = func1() + 200 list1 = [100, func1()] dict1 = {'a': 100, 'b': func1()} print(list1) print(dict1) def func2(): return '10,20' print(func2().split('20')) print(func2()[0])
-
-
函数调用过程
-
回到函数定义位置
-
传参 (用实参给形参赋值, 这个时候要保证每个参数都有值)
-
执行函数体
-
执行完函数体时确定返回值
(看执行函数体时, 是否遇到return, 如果遇到, 其后内容就是返回值内容, 并且此时函数直接结束
如果没有遇到return, 返回值是none -
回到函数调用的位置(此时,函数调用表达式的值才是函数的返回值)
def func3(): print('=============') return 100 print('-----------------------') print(func3()) # python的函数只有一个返回值 def func4(): return '10', '20' print(func4())
# 练习: 写一个函数通过指定方法来计算多个多个结果 # operation('+', 10, 20, 30) -> 求: 10+20+30 # operation('*', 3, 4, 5, 6) -> 求 3*4*5*6 # operation('-', 10, 3, 4) -> 求: 10-3-4 # operation('/', 19, 2) -> 求 19/2 def operation(means:str, *nums): if not nums or means not in('+', '-', '*', '/'): return None if means == '+': count = 0 for x in nums: count += x return count if means == '*': count = 1 for x in nums: count *=x return count if means == '-': count = nums[0] for x in nums[1:]: count -= nums[x] return count if means == '/': count = nums[0] for x in nums[1:]: count /= nums[x] return count else: return None # req = ('+', 1, 2, 3, 4) print(operation('+', 1, 2, 3, 4)) print(operation('-', 4,1)) print(operation('*', 1, 2, 3, 4)) print(operation('/', 4, 2, 1))
-
-
-
变量的作用域
-
变量中的作用域 - 已经定义过的变量能使用的范围
- 根据变量的作用域不同, 将变量分为全局变量和局部变量两种
-
全局变量
-
定义在函数或者类外部的变量就是全局变量;
-
全局变量的作用域: 从定义开始到程序结束的任何位置都可以使用
# a、b和x都是全局变量 a =10 for x in range(5): b = 20 print(f'循环里面a:{a}') print('循环外面:',x)
-
-
局部变量
-
定义在函数里面的变量就是局部变量(形参也是局部变量)
-
局部变量的作用域: 从定义开始到函数结束
# c和d都是局部变量 def func2(c = 3): d = 100 print(f'函数内部c:{c}, d:{d}') func2() # print(f'函数外部c:{c}, d:{d}')
-
-
函数调用过程就是压栈的过程
- 调用函数的时候, 系统会自动在栈区间为这个函数差创建一个临时栈区间, 用来保存在函数中产生的据(局部变量)
- 当函数调用结束, 这个临时栈区间会自动释放 (释放之前会将返回值传递到临时栈区间的外部).
-
global
-
在函数中修改一个全局变量的值或者在函数定义一个全局变量
global 变量名
使用变量num = 30 m = 20 def func3(): num = 40 #不是在修改全局变量num的值, 而是定义一个新的局部变量 print(f'函数内部num:{num}') global m print(f'函数内部m:{m}') m = 200 #在函数中修改一个全局变量的值, 需要先有global进行修改 func3() print(f'函数外部num:{num}') print(f'函数外部m:{m}')
-
-
作业
- 编写一个函数,计算一个整数的各位数的平方和
例如: sum1(12) -> 5(1的平方加上2的平方) sum1(123) -> 14
def sum_sqrt():
num = int(input('请输入一个整数:'))
count = 0
if num >=0:
for x in str(num):
count += int(x)**2
return count
else:
for x in str(num)[1:]:
count += int(x)**2
return count
- 写一个函数,求一个数字列表中绝对值最大的元素
例如:nums = [-23, 100, 89, -56, -234, 123], 最大值是:-234
import math
def new_max(list):
max = list[0]
for x in list[1:]:
if math.fabs(x) > math.fabs(max):
max = x
return '最大值:', max
-
编写函数实现字符串join方法的功能,将指定序列中的元素通过指定字符串合并成一个新的字符串
def new_join(seq:str, char:str): str1 = seq.replace(', ', char, len(seq)-1) return str1
-
写一个函数实现列表extend的功能,将指定序列中的元素全部添加到指定列表中
def new_extend(list1:list,list2:list): list3 = [] for x in list1: list3.append(x) for x in list2: list3.append(x) return list3
-
写一个函数实现简易计算器的功能:输入第一个数字,输入运算符,输入第二个数字,计算结果。
执行过程1:
计算器:
>10
>+
>20
=30
执行过程1:
计算器:
>10
>x
>20
=200
....
def cal():
num1 = int(input('请输入第一个数字:'))
operator = input('请输入运算符:')
num2 = int(input('请输入第二个数字:'))
if operator not in ('+', '-', '*', '/'):
return None
if operator == '+':
return num1 + num2
if operator == '*':
return num1 * num2
if operator == '-':
return num1 - num2
if operator == '/':
return num1 / num2
else:
return None
- 已经列表points中保存的是每个点的坐标(坐标是用元组表示的,第一个值是x坐标,第二个值是y坐标)
points = [
(10, 20), (0, 100), (20, 30), (-10, 20), (30, -100)
]
1)获取列表中y坐标最大的点
def max_y():
list1 = [x[1] for x in points]
a = list1.index(max(list1))
return points[a]
2)获取列表中x坐标最小的点
def min_x():
list1 = [x[0] for x in points]
a = list1.index(min(list1))
return points[a]
3)获取列表中距离原点最远的点
def far_point():
list1 = [math.sqrt(x[0]**2 + x[1]**2) for x in points]
a = list1.index(max(list1))
return points[a]
4)将点按照点到x轴的距离大小从大到小排序
list2 = []
list3 = []
set1 = {math.fabs(x[1]) for x in points}
list1 = sorted(set1, reverse=True)
for x in list1:
for y in range(len(points)):
if math.fabs(points[y][1]) == x:
pass
list3.append(points[y])
print(list3)