python基础(四)
本文的练习是基于前三章的练习进行函数的改写。
这是python基础的最后一个章节。大家在看文档时候,也可以配套下面的网站进行学习,效果事半功倍。
文章目录
- 一、函数 function
-
- pycharm相关设置
- 定义
- 定义函数
- 调用函数
- 返回值
- 函数内存图
- 可变/不可变类型在传参时的区别
- 二、作用域 LEGB
-
- 变量名的查找规则
- 局部变量
- 全局变量
- global语句
- 函数参数
-
- 实际参数
- 形式参数
- 参数自左至右的顺序位置
一、函数 function
pycharm相关设置
“代码自动完成”时间延时设置
File -> Settings -> Editor -> General -> Code Completion -> Autopopup in (ms):0.
快捷键:
Ctrl +P 参数信息(在方法中调用参数)
Ctrl + Q 快速查看文档
Ctrl + Alt+ M 提取方法
定义
- 用于封装一个特定的功能,表示一个功能或者行为。
- 函数是可以重复执行的语句块,可以重复调用。
定义函数
语法:
def 函数名(形式参数):函数体
说明:
def关键字∶全称是define,意为“定义”。
函数名∶对函数体中语句的描述,规则与变量名相同。
形式参数︰方法定义者要求调用者提供的信息。
函数体∶完成该功能的语句。
函数的第一行语句建议使用文档字符串描述函数的功能。
调用函数
语法:函数名(实际参数)说明:根据形参传递内容。
""" 自定义函数"""#定义(做功能)函数def attack01(): """ 单次攻击 """ print("临门一脚") print("直拳") print("摆拳") print("肘击")def attack02(count):#count是形式参数 """ :param count: 攻击次数,int类型 """ for i in range(count): print("临门一脚") print("直拳") print("摆拳") print("肘击")#调用函数attack01()#调用函数attack01()#调用函数attack01()print("----------------")#调用函数#3是实际参数attack02(3)运行结果:临门一脚直拳摆拳肘击临门一脚直拳摆拳肘击临门一脚直拳摆拳肘击----------------临门一脚直拳摆拳肘击临门一脚直拳摆拳肘击临门一脚直拳摆拳肘击
练习1:将下列代码,定义到函数中,再调用一次。
for r in range(3): #内层循环控制列#0123 0123 0123 for c in range(4): print("*", end="") print()
def print01(r_count,c_count,char): """ 打印矩形 :param r_count: 行数 :param c_count: 列数 :param char: 填充的字符 """ for r in range(r_count): #内层循环控制列#0123 0123 0123 for c in range(c_count): print(char, end="") print()print01(3,4,"#")运行结果:############
练习2:定义在控制台中打印一维列表的函数。
【例如[1,2,3]—>1 2 3 每个元素一行】
def print02(list_target): """ 打印列表 :param list_target: 一维数组列表 """ for item in list_target: print(item)print02([1,2,3])print02(["a",True,1,1.5])运行结果:123aTrue11.5
练习3:定义在控制台中打印二维列表的函数。
例如:
[[1,2,3,44],[4,5,5,5,65,6,87],[7,5]]变成:1 2 3 44,4 5 5 5 65 6 877 5
def print_list(list_target): """ 打印二维列表 :param list_target:需要打印的二维列表 """ for item in list_target: for i in range(len(item)): print(item[i],end = " ") print()list01=[[1,2,3,44],[4,5,5,5,65,6,87],[7,5]]print_list(list01)运行结果:1 2 3 44 4 5 5 5 65 6 87 7 5
练习4:(扩展)方阵转置,不用做成函数
提示:详见图片
思路:# (0,1)(0,2)(0,3)# (1,2)(1,3)# (2,3)list02= [ [1,2,3,4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16],]# 方法一:for r in range(len(list02)-1): for c in range(r+1,len(list02)): temp = list02[r][c] list02[r][c]=list02[c][r] list02[c][r] = tempprint(list02)# 方法二:for r in range(1,len(list02)): for c in range(r,len(list02)): list02[c][r-1],list02[r-1][c] = list02[r-1][c],list02[c][r-1]print(list02)运行结果:[[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
返回值
定义:方法定义者告诉调用者的结果。
语法∶return 数据
""" 函数返回值 语法"""#参数∶调用者传递给定义者的信息#返回值∶定义者传递给调用者def fun01(a) : print ("fun01执行喽") # 作用∶1.返回结果2.退出方法 return 20 print ("fun01执行喽")#F8逐过程(调试时跳过方法)#F7逐语句(调试时进入方法)re = fun01(10)print(re)#fun01执行喽# 20def fun02(a) : print ("fun01执行喽")re = fun02(10)print(re)# fun01执行喽# None
""" 函数返回值 应用"""#设计思想:分而治之(干一件事)#需求∶定义两个数字相加的函数# 不能这么做# def add():# 1.获取数据# number01 = int(input("请输入第一个数学︰"))# number02 = int(input("请输入第二个数学︰"))# 2.逻辑计算# result = number01 + number02# 3.显示结果# print(result)# add()def add(number01,number02): #逻辑处理 return number01 + number02#调用者提供数据number01 = int(input("请输入第一个数学︰"))number02 = int(input("请输入第二个数学︰"))result = add(number01,number02)#调用者负责显示结果print("结果是:"+ str(result))运行结果:请输入第一个数学︰1请输入第二个数学︰2结果是:3
练习1:定义计算四位整数,每位相加和的函数。
def each_unit_sum(num): """ 计算整数的每位相加和 :param num:四位整数 :return:相加的结果 """ result = num % 10 # 累加十位 result += num // 10 % 10 # 累加百位 result += num // 100 % 10 # 累加千位 result += num // 1000 return resultnum = int(input("请输入四位数字:"))re = each_unit_sum(num)print("结果是:" + str(re))运行结果:请输入四位数字:1234结果是:10
练习2:定义根据两,计算几斤零几两的函数。
def weight_conversion(weight): """ 根据两,计算几斤零几两 :param weight:需要计算的两 :return:元组(斤,两) """ w1 = weight // 16 w2 = weight % 16 return (w1,w2)weight01 = int(input("请输入两:"))result = weight_conversion(weight01)print("总计:"+str(result[0])+"斤零"+str(result[1])+"两")运行结果:请输入两:1234总计:77斤零2两
练习3:定义根据成绩计算等级的函数。
def get_grade_level(grade): if grade > 100 or grade <0: return "输入有误" if grade >= 90: return "优秀" if grade >= 80: return "良好" if grade >= 60: return "及格" return "不及格"grade01 = float(input("请输入成绩:"))re = get_grade_level(grade01)print(re)运行结果:请输入成绩:80良好
练习4:定义判断列表中是否存在相同元素的函数。
def is_repeating(list01): for r in range(len(list01) - 1): for c in range(r + 1, len(list01)): if list01[r] == list01[c]: return True #有重复 return False #没有重复list02 = [3,81,3,5,81,1]re = is_repeating(list02)print(re)运行结果:True
练习5:定义函数,根据年月,计算有多少天。考虑闰年29天,平年28天。
def is_leap_year(year): return year % 4 == 0 and year % 100 != 0 or year % 400 == 0#不建议方法的返回值类型可能是多种def get_day_by_month(year,month): if month < 1 or month > 12: return 0 if month == 2: return 29 if is_leap_year(year) else 28 if month in (4, 6, 9, 11): return 30 return 31year01 = int(input("请输入年份∶"))month01 = int(input("请输入月份∶"))print(get_day_by_month(year01,month01))运行结果:请输入年份∶2022请输入月份∶228
函数内存图
""" 函数内存图"""#在方法区中存储函数代码,不执行函数体def fun01(a): a=100num01 = 1#因为调用函数﹐所以开辟一块内存空问,叫做栈帧#栈帧用于存储在函数内部定义的变量(包含参数)fun01(num01)#函数执行完毕后﹐栈帧立即释放(其中定义的变量也会销毁)print(num01)#1def fun02(a) : # 改变的是传入的可变对象 a[0] = 100 # print(a)#[100]list01 = [1]fun02(list01)print(list01[0])#100def fun03(a) : # 改变的是fun03栈帧中的变量a的指向 a = 100 # print(a)#[100]list01 = [1]fun03(list01)print(list01[0])#1
练习:
def fun04(a) : a[1] =[200]list01 = [ 1,[2,3]]fun04(list01)print(list01[1])#[200]
练习1:定义列表升序排列的函数。
def sort(list_target): # 传入的是可变对象 # 函数体修改的是传入的对象 for r in range(len(list_target) - 1): for c in range(r+1, len(list_target)): if (list_target[r] > list_target[c]): list_target[r], list_target[c] = list_target[c], list_target[r]list01 = [3,80,45,5,7,1]sort(list01)print(list01)运行结果:[1, 3, 5, 7, 45, 80]
练习2:定义方阵转置函数
def square_matrix_transpose(sqr_matrix): """ 方阵转置 :param sqr_matrix:二维列表类型的方阵 """ for r in range(1, len(sqr_matrix)): for c in range(r, len(sqr_matrix)): sqr_matrix[c][r - 1], sqr_matrix[r - 1][c] = sqr_matrix[r - 1][c], sqr_matrix[c][r - 1]list02= [ [1,2,3,4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16],]#矩阵转置的转置等于原矩阵square_matrix_transpose(list02)print(list02)square_matrix_transpose(list02)print(list02)运行结果:[[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]][[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
可变/不可变类型在传参时的区别
不可变类型参数有:
- 数值型(整数,浮点数,复数)
- 布尔值 bool
- None 空值
- 字符串 str
- 元组 tuple
- 固定集合 frozenset
可变类型参数有:
- 列表 list
- 字典 dict
- 集合 set
传参说明:
- 不可变类型的数据传参时,函数内部不会改变原数据的值。
- 可变类型的数据传参时,函数内部可以改变原数据。
二、作用域 LEGB
- 作用域∶变量起作用的范围。
- Local局部作用域∶函数内部。
- Enclosing外部嵌套作用域︰函数嵌套。
- Global全局作用域∶模块(.py文件)内部。
- Builtin内置模块作用域∶builtins.py文件。
变量名的查找规则
由内到外:L ->E -> G ->B
局部变量
- 定义在函数内部的变量(形参也是局部变量)
- 只能在函数内部使用
- 调用函数时才被创建,函数结束后自动销毁
全局变量
- 定义在函数外部,模块(文件)内部的变量。
- 在整个模块(py文件)范围内访问(但函数内不能将其直接赋值)。
global语句
作用:
- 在函数内部修改全局变量。
- 在函数内部定义全局变量(全局声明)。
语法∶global 变量1,变量2,…
""" 作用域:"""#全局变量g01 = "ok"def fun01(): # 局部变量∶在函数内部定义的变量 lo1 = 200 print(lo1)#200 # 在函数内部可以读取全局变量 # print(g01)#ok #创建了一个局部变量q01,而不是修改全局变量 # g01 = "no" # print(g01) # no # 定义全局变量g01 # 此时修改的是全局变量 global g01 g01 = "no" print(g01) # no # 定义全局变量g02 global g02 g02 = 250fun01()print(g01) # noprint(g02)#250
内存图:
练习:记录一个函数fun01的执行次数。
def fun01(): pass fun01()fun01()fun01()fun01()fun01()print("调用?次")
count = 0def fun01(): global count count += 1fun01()fun01()fun01()fun01()fun01()fun01()print("调用%d次"%count)运行结果:调用6次
函数参数
实际参数
""" 函数参数 实际参数"""def fun01(a,b,c,d): print(a) print(b) print(c) print(d)#1,2,3,4 是位置实参:实参与形参的位置进行依次对应fun01(1,2,3,4)# 1# 2# 3# 4#关键字实参:实参与形参根据名称进行对应fun01(b=1,d=2,c=3,a=4)# 4# 1# 3# 2#序列实参:星号将序列拆分后按位置与形参进行对应# 如果参数很多,可以存储在序列(字符串/列表/元组)中# 再通过*拆分,直接传入函数list01 = ["a","b","c","d"]fun01(*list01)# a# b# c# d#字典实参:双星号将字典拆分后按名称与形参进行对应# 如果参数很多,可以存储在字典中# 再通过**拆分,传入函数dict01 = {"a":1,"c":3,"d":4,"b":2}fun01(**dict01)# 1# 2# 3# 4
形式参数
""" 函数参数 形式参数"""#缺省(默认)参数:如果实参不提供,可以使用默认值def fun01(a=None,b=0,c=0,d=0): print(a) print(b) print(c) print(d)# 关键字实参+缺省形参:调用者可以随意传递参数fun01(b=2,c=3)# 100# 2# 3# 0#位置形参def fun02(a,b,c,d): print(a) print(b) print(c) print(d)#3.星号元组形参:*将所有实参合并为一个元组# 作用:让实参个数无限def fun03(*args): print(args)fun03() #()fun03(1)#(1,)fun03(1,"2")#(1, '2')fun03(1,2)#(1, 2)#4.命名关键字形参:在星号元组形参以后的位置形参# 目的︰要求实参必须使用关键字实参.def fun04(a, *args,b) : print(a) print(args) print(b)fun04(1,b=2)fun04(1,2,3,4,b=2)# 1# ()# 2# 1# (2, 3, 4)# 2def fun05(*,a,b): print(a) print(b)fun05(a=1,b=2)# 1# 2#5.双星号字典形参:**目的是将实参合并为字典# 实参可以传递数量无限的关键字实参def fun06(**a) : print(a)fun06(a=1,b=2)#{'a': 1, 'b': 2}
练习1:定义函数,根据小时,分钟,秒,计算总秒数。要求如下∶
可以只计算小时–>秒
可以只计算分钟–>秒
可以只计算小时+分钟–>秒
可以只计算小时+秒–>秒
def get_total_second (hour=0,minute=0, second=0): return hour * 3600 + minute * 60 + second#小时,分钟,秒print(get_total_second(1,1,1))#小时,分钟print(get_total_second(2,3))#分钟.秒print(get_total_second(minute=2,second=1))#小时print(get_total_second(2))#分钟print(get_total_second(minute=2))# 3661# 7380# 121# 7200# 120
练习2:定义函数,数值相加的函数。
def num_add(*args): i=0 for item in args: i += item return iprint(num_add(1,2))#3# 或者:def num_add(*args): return sum(args)print(num_add(1,2))#3
参数自左至右的顺序位置
位置形参–>星号元组形参–>命名关键字形参–>双星号字典形参
#调用fun07def fun07(a,b,*args,c,d,**kwargs): print(a) print(b) print(args) print(c) print(d) print(kwargs)fun07(1,2,1,2,c=3,d=4,m=2,n=4,a1=2)运行结果12(1, 2)34{'m': 2, 'n': 4, 'a1': 2}