day10
总结
1. 函数
-
位置参数和关键字参数(根据实参的提供的不同将实参分为位置参数和关键字参数)
""" 1) 位置参数:调用函数的时候让实参和形参在位置上一一对应 2) 关键字参数:调用函数的时候以’形参名=值‘的形式确定形参对应的实参。 3) 位置关键字和关键字参数混用: 位置参数必须在关键字参数前面,必须保证每个参数都会有一次赋值 """ def func1(x, y, z): print(f'x:{x},y:{y},z:{z}') # 位置参数 func1(10, 20, 30) # x:10,y:20,z:30 # 关键字参数 func1(x=10, z=20, y=30) # x:10,y:30,z:20 func1(20, z=100, y=200) # x:20,y:200,z:100 # func1(x=100, 20, z=400) # SyntaxError: positional argument follows keyword argument
-
参数默认值 - 定义函数的时候可以直接在形参后面用=给形参赋默认值
# 有默认值的参数在调用的时候可以不用传参 # 如果有的参数有默认值有的没有,有默认值的参数必须放在没有默认值的后面 # def func3(x=100, y): # SyntaxError: non-default argument follows default argument # print(f'x:{x}, y:{y}') def func2(x, y, z=100, i=200, j=400): print(f"x:{x}, y:{y}, z:{z}, j:{j}, i:{i}") func2(10, 40) # x:10, y:40, z:100, j:400, i:200 func2(10, 30, i=1000) # x:10, y:30, z:100, j:400, i:1000 print(10, 20, end='\n', sep=',') # 10,20
-
参数类型说明 - 仅对参数类型进行说明,不做约束
# 无默认值参数的类型说明 - 形参: 类型名-例如:int # 有默认值的参数,默认值的类型就是参数对应的类型 def func4(x: str, y=1) -> None: pass print(f'str:{x}, y:{y}') func4([1, 2, 3], 2) # str:[1, 2, 3], y:2
-
不定长参数
""" 1) 带*的不定长参数:在某个形参前加*,那么这个形参就是一个不定长形参,它可以接收任意多个实参 带*的本质就是一个元组,对应的实参是元组中的元素 注意:带*的不定长参数对应的实参必须用位置参数传参, 带*号前传入参数只能用位置参数,带*号后传入传入参数只能用关键字参数,所以默认不带默认值的形参放在带*号的形参前,有默认的形参写在带*号的形参之后 2) 带**的不定长参数:在某个形参前加**,那么这个形参就是一个不定长参数,它可以接受任意多个数的参数 带**的参数本质就是一个字典,对应的关键字参数就是字典中的键值对 注意:**的不定长参数对应的参数必须用关键字传参 """ # 定长参数在*的不定长参数前,定长和不定长都适用于位置参数传参 def func5(y=10, *x, z): pass print(f'y:{y}, x:{x}, z:{z}, type(x):{type(x)}') # func5(x=(100, 30)) # TypeError: func5() got an unexpected keyword argument 'x' # func5() func5(19, 38, 25, 100, 2343, z=10) # y:19, x:(38, 25, 100, 2343), z:10, type(x):<class 'tuple'> # func5(19, 38, 25, 100, 2343, z=10, y=120) # TypeError: func5() got multiple values for argument 'y' # func5(19, 38, 25, 100, 2343, 10) # TypeError: func5() missing 1 required keyword-only argument: 'z' def func6(z, *x): print(f'z:{z}, x:{x}') def func7(x, y, z=10): print(f"x:{x}, y:{y}, z:{z}") print('===================================================') # 3) **的使用 def func9(**x): pass print(f"x:{x}") func9(x=10, a=10, b=12) # x:{'x': 10, 'a': 10, 'b': 12} # 4) 定长参数在**的不定长前,定长既可以用位置参数也可以用关键字参数 def func10(x, **y,): pass print(f"x:{x}, y:{y}") func10(x=2, a=10) # x:2, y:{'a': 10} func10(2, a=10) # x:2, y:{'a': 10} # 5) 定长参数不能放在**的不定长参数后面 # def func11(**y, *y): # SyntaxError: invalid syntax # pass # 6) 带*的不定长参数和带**的不定长参数可以一起使用,带*的必须放在带**的前面 def func11(*args, **kwargs): pass print(args, kwargs) func11() # () {} func11(1, 2, 3) # (1, 2, 3) {} func11(a=10) # () {'a': 10}
-
返回值(返回值的作用就是将函数内部的数据传递到函数外部)
# 在函数体中用return关键字来返回返回值(一个函数只有一个返回值) # 什么时候需要返回值;如果函数的功能产生了新的数据,将新的数据返回 def sum2(num1=0, num2=0): return num2 + num1
-
字母确定函数返回值 - 怎么将函数内部的数据传递到外部
-
怎么获取函数返回值
# 获取函数调用表达式的值就是获取函数返回值 # 函数调用表达值 - 调用函数的语句 # 函数调用表达式的值就是函数返回值,函数返回值能做的事,函数表达式都可以做 result = sum2(10, 30) # 40 print(result) print(sum2(10, 20)) # 30 a = result + 10 a = sum2(10, 30) + 10 def func1(): return [10, 20] print([10, 20][-1]) # 20 print(func1()[-1]) # 20 list1 = func1() list1.append('hello') list1.insert(0, 'hhhh') list1.extend([10, 20, 30]) del list1[0] list1.remove('hello') list1.pop(3) list1[0] = 100 print(list1) # [100, 20, 10, 30] def func2(): return 10, 20 for x in func2(): print(x) print(len(func2())) print(max(func2()))
-
函数调用过程
""" 第一步:回到函数定义的位置 第二步:传参(用实参给形参赋值,这个时候要保证每个参数都有值) 第三步:执行函数体 第四步:执行完函数体,确认返回值 (看执行函数体的时候有没有遇到returnj, 如果遇到return,return后面的值是什么,函数的返回值就是什么,并且在遇到 return的时候函数直接结束。如果没有遇到return,函数返回值就是None) 第五步:回到函数调用的位置(这个时候函数调用表达式的值才是函数的返回值) """ def func3(): print('---------') return return 100 print('==========') print('+++++++') print(func3()) def func4(): return 10, 20 print(func4()) # 练习:写一个函数通过指定方式来计算多个数的结果 # operation('+', 10, 20, 30) -> 求: 10+20+30 # operation('*', 3, 4, 5, 6) -> 求:3*4*5*6 def my_operation(operator: str, *nums) -> (int, None): if nums: if operator == '+': sum1 = 0 for num in nums: sum1 += num return sum1 # return sum(nums) elif operator == '*': res = 1 for num in nums: res *= num return res elif operator == '-': res = nums[0] for num in nums[1:]: res -= num return res elif operator == '/': dividend = nums[0] for divisor in nums[1:]: dividend /= divisor return dividend res = my_operation('/', 1, 3, 4, 5) print(res) # 0.016666666666666666 res = my_operation('-', 10, 32, 43, 1) print(res) # -66 res = my_operation('+', 1, 2, 3, 4, 5) print(res) # 15 res = my_operation('*', 13, 43, 23, 5, 2) print(res) # 128570 def odevity(num: int): if num % 2: return '奇数' return '偶数'
2. 作用域
-
变量的作用域 - 已经定义过的变量能使用范围
-
全局变量
""" 没用定义在函数里或类里面的变量就是全局变量; 全局变量的作用域:从定义开始到程序结束的任何位置都可以使用 """ # a, b, x都是全局变量 a = 10 for x in range(10): # 全部变量 b = x print(a, b, x) # 10 9 9 def func1(): print(a, b, x) func1() # 10 9 9
-
局部变量
"""
定义在函数里的变量就是局部变量(形参也是局部变量)
局部变量的作用域:从定义开始到函数结束
"""
# c, d都是局部变量
def func2(c=3):
d = 100
func2()
-
函数调用过程就是压栈的过程
""" 调用函数的时候,系统会自动在栈区间为这个函数创建一个临时栈区间,用来保持在函数中产生的数据(局部变量)。 当函数调用结束,这个临时栈区间会自动释放(释放之前会将返回值传递到临时栈区间的外部)。 """
-
global - 在函数内部
""" 在函数中修改一个全局变量的值或者在函数定义一个全局变量 语法: gloabl 变量 使用变量 """ num = 30 m = 100 def func4(): num = 40 # 不是在修改全局变量num的值,而是定义一个新的局部变量 print(f"函数内部num:{num}") # 函数内部num:40 global m m = 200 # 在函数中修改一个全局变量的值,需要先用global进行说明 print(f"函数内部m:{m}") # 函数内部m:200 global n n = 'abc' func4() print(f"函数外部num:{num}") # 函数外部num:30 print(f"函数外部m:{m}") # 函数外部m:200 print(f"函数外n:{n}") # 函数外n:abc
作业
- 编写一个函数,计算一个整数的各位数的平方和
例如: sum1(12) -> 5(1的平方加上2的平方) sum1(123) -> 14
def sum1(num: int) -> int:
"""
计算一个整数的各位数的平方和
:param num: 需要计算的整数
:return: 该数的各位数的平方和
"""
if type(num) != int:
return None
res = 0
if num >= 0:
for x in str(num):
res += int(x)**2
else:
for x in str(num)[1:]:
res += int(x) ** 2
return res
print(sum1(-123)) # 14
- 写一个函数,求一个数字列表中绝对值最大的元素
# 例如:nums = [-23, 100, 89, -56, -234, 123], 最大值是:-234
def abs_max_list(list1: list):
"""
求一个数字列表中绝对值最大的元素
:param list1: 传入数字列表
:return: 列表中元素绝对值最大对应的元素
"""
if type(list1) != list or not list1:
return None
# value = list1[0]
abs_max = abs(list1[0])
for x in list1[1:]:
if abs_max < abs(x):
abs_max = abs(x)
# value = x
# return value
return [x for x in list1 if x in [abs_max, -abs_max]]
print(abs_max_list([-23, 100, 89, -56, -234, 123])) # -234
-
编写函数实现字符串join方法的功能,将指定序列中的元素通过指定字符串合并成一个新的字符串
def sequence_join(sequence, joinstr: str): """ 将指定序列中的元素通过指定字符串合并成一个新的字符串 :param sequence: 需要拼接的序列 :param joinstr: 拼接字符串 :return: 新字符串 """ if not sequence: return None res = '' for x in sequence[:-1]: res += str(x) + joinstr res += str(sequence[-1]) return res print(sequence_join([-23, 100, 89, -56, -234, 123], '+')) # -23+100+89+-56+-234+123
-
写一个函数实现列表extend的功能,将指定序列中的元素全部添加到指定列表中
def list_extend(list1: list, sequence): """ 将指定序列中的元素全部添加到指定列表中 :param list1: 指定列表 :param sequence: 指定序列 :return: None """ for x in sequence: list1.append(x) list1 = [-23, 100, 89, -56, -234, 123] list_extend(list1, (12, 110)) print(list1)
-
写一个函数实现简易计算器的功能:输入第一个数字,输入运算符,输入第二个数字,计算结果。
执行过程1: 计算器: >10 >+ >20 =30 执行过程1: 计算器: >10 >x >20 =200 ....
def calculator(): """ 简易计算器 :return: None """ num1 = float(input('>')) if num1 % 1 == 0: num1 = int(num1) operator = input('>') num2 = float(input('>')) if num2 % 1 == 0: num2 = int(num2) if operator == '+': print(f'={num1 + num2}') elif operator == '-': print(f'={num1 - num2}') elif operator == 'x' or operator == 'X': print(f'={num1 * num2}') elif operator == '/': print(f'={num1 / num2}') elif operator == '%': print(f'={num1 % num2}') else: print('暂时无法进行该运算符的计算,请尽情期待下一个版本!') calculator()
-
已经列表points中保存的是每个点的坐标(坐标是用元组表示的,第一个值是x坐标,第二个值是y坐标)
points = [ (10, 20), (0, 100), (20, 30), (-10, 20), (30, -100) ] def get_max_y_from_points(points: list): """ 获取列表中y坐标最大的点 :param points: 要进行操作的坐标列表 :return: 列表中y坐标最大的点 """ if not points: return None max_y_point = points[0] for x, y in points[1:]: if max_y_point[-1] < y: max_y_point = (x, y) return max_y_point def get_min_x_from_points(points: list): """ 获取列表中x坐标最小的点 :param points: 要进行操作的坐标列表 :return: 列表中x坐标最小的点 """ if not points: return None min_x_point = points[0] for x, y in points[1:]: if min_x_point[0] > x: min_x_point = (x, y) return min_x_point def get_max_distance_from_points(points: list): """ 获取列表中距离原点最远的点 :param points: 要进行操作的坐标列表 :return: 列表中距离原点最远的点 """ if not points: return None max_distance_point = points[0] max_distance_square = max_distance_point[0]**2 + max_distance_point[-1]**2 for point in points: if max_distance_square < point[0]**2 + point[-1]**2: max_distance_point = point return max_distance_point def points_sort_by_x_distance(points: list): """ 将点按照点到x轴的距离大小从大到小排序 :param points: 要进行操作的坐标列表 :return: 按照点到x轴的距离大小从大到小排序后的列表 """ if not points: return None new_points = [] list1 = sorted({abs(x[-1]) for x in points}, reverse=True) for value in list1: new_points.extend([x for x in points if x[-1] in [value, -value]]) return new_points
1)获取列表中y坐标最大的点
max_y_point = get_max_y_from_points(points) max_y_points = [x for x in points if x[-1] == max_y_point[-1]] print(max_y_points)
2)获取列表中x坐标最小的点
min_x_point = get_min_x_from_points(points) min_x_points = [x for x in points if x[0] == min_x_point[0]] print(min_x_points)
3)获取列表中距离原点最远的点
max_distance_point = get_max_distance_from_points(points) max_distance_points = [x for x in points if x[0]**2 + x[-1]**2 == max_distance_point[0]**2 + max_distance_point[-1]**2] print(max_distance_points)
4)将点按照点到x轴的距离大小从大到小排序
# 方法一 points = points_sort_by_x_distance(points) # 方法二 points.sort(reverse=True, key=lambda x: abs(x[-1])) print(points)