一、上堂回顾
1.默写题目
1.已知字符串str = "aBcedf",完成下面操作
a.获取字符串的长度
b.统计子字符串“a"在str中出现的次数
c.判断原字符串是否是以“abc”开头的
d.将其中的大写字母转换为小写
e.将其中的“def”替换为"hello"
f.获取"c"在原字符串中第一次出现的下标
str = "aBcedf" l = len(str) c = str.count("a") result1 = str.startswith("abc") newStr = str.lower() str.replace("def","hello") index1 = str.find("c") #-1 index2 = str.index("c") #报错
2.定义函数,求任意两个数的和
def myAdd(a,b): sum = a + b print(sum) a = 10 b = 20 myAdd(a,b) print(myAdd(a,b)) #None def myAdd1(a,b): sum = a + b return sum result = myAdd1(a,b) print(result) print(myAdd1(a,b))
2.知识点回顾
本质:是对特殊功能的封装
作用:简化代码,提高可维护性
定义:def
调用:函数名(实参)
参数:形参和实参,赋值的过程【传参】参数的传递:值传递和引用传递【不可变类型和可变类型】
注意:实参的数量和类型取决于形参
二、函数
1.函数概述
#需求:半径分别为r1 = 10,r2 =9.4,r3 = 22,求圆的面积 r1 = 10 r2 =9.4 r3 = 22 s1 = 3.14 * r1 ** 2 s2 = 3.14 * r2 ** 2 s3 = 3.14 * r3 ** 2 #使用函数优化 def area(radius): s = 3.14 * radius ** 2 area(r1) area(r2)
在一个完整的项目中,某些功能会被反复使用,那么将该功能对应的代码封装成函数,当要再次使用这个功能的时候直接使用即可
本质:函数是对某个特殊功能的封装
优点:
a.简化代码结构,提高程序的模块性
b.提高代码的复用性
c.提高代码的可维护性【如果需求发生改变,则只需要更改函数内部】
2.函数使用
定义函数
语法:
def 函数名(参数1,参数2...):
函数体
return 表达式或者常量或者变量
说明:
a.一个完整的函数由两个部分组成:函数的声明和函数的实现
b.def:definition,定义,函数是以def定义的
c.函数名:标识符,只需要遵循标识符的规则即可,尽量做到见名知意
d.(参数1,参数2...):()表示参数的开始和结束,其中参数1,参数2...被称为参数列表,本质上其实就是一个变量,参数列表也可以为空
e.函数体:需要被封装的特殊功能
f.return :返回,一般用于结束函数,并且将返回值携带给函数的调用者,不带任何数据的return其实相当于返回None
2.1简单的函数
简单的函数:无参无返回值的函数
代码演示:
#定义无参无返回值的函数 def myPrint(): print("hello world") #注意:函数定义好之后,不会自动执行,需要手动进行调用 """ 调用格式:函数名(实际参数) 说明: a.出现在函数声明部分的参数被称为形式参数,简称形参,本质是一个变量 【形参 = 实参】 b.出现在函数调用部分的参数被称为实际参数,简称实参,本质上是一个数据 注意: a.进行传参的时候,实参和形参需要保持匹配 b.如果形参为空,则调用函数的时候,()也不能省略 c.函数调用的本质:实参给形参赋值的过程 """ myPrint() myPrint() myPrint() myPrint() myPrint() #注意如果在同一个py文件中,出现同名的函数,则后出现覆盖掉先出现的 def myPrint(): print("hello Python") myPrint()
2.2函数的调用
代码演示:
#函数的调用 def show1(): print("aaaaa") show2() def show2(): print("bbbbbb") show3() def show3(): print("ccccc") show1() #show2() #show3() #函数入栈
2.3函数的参数
函数的调用:实参给形参赋值的过程,被称为传参
代码演示:
#定义一个有参的函数 def myFunc(str,age): print(str,age) #str = s1 age = a1 s1 = "abc" a1 = 10 myFunc(s1,a1) #注意:形参的数据类型取决于:实参的类型,具体的需求 def myFunc1(str,age,hobby): print(str,age,hobby) age += 1 #注意:实参和形参进行严格的匹配【类型,数量】 myFunc1("abc",10)
2.4参数的传递
1>值传递:传递的是不可变的数据类型,比如number,string,tuple
2>引用传递:传递的是可变的数据类型,比如list,dict,set
代码演示:
#值传递 def fun1(a): print(id(a)) a = 10 print(id(a)) temp = 20 print(id(temp)) #a = temp fun1(temp) print(temp) #a的值发生改变,对temp的值没有影响 #引用传递 def fun2(c): c[1] = 100 print(c) d = [10,20,30,40] fun2(d) print("d = ",d) #变量中存储的是地址
三、函数的基本使用【掌握】
1.参数的类型
1.1必需参数
调用函数的时候,必须以正确的顺序传参,传参的时候参数的数量和类型必须保持完全一致
代码演示:
#必需参数 #无参的函数 def test1(): pass #有参的函数 def test2(a): pass def test3(a,b,c): pass #调用 test1() test2(10) test3(10,20,30)
1.2关键字参数
print(10,20,end=" ")
使用关键字参数允许函数调用的时候 实参的顺序和形参的顺序可以不一致,可以根据关键字进行自动的匹配
代码演示:
#关键字参数 def fun1(name,age): age += 1 print(name,age) #正常调用函数 fun1("lisi",10) #使用关键字参数调用函数 fun1(name="zhangsan",age=20) #fun1(30,name="jack") fun1("lisi",age=30) #注意;关键字参数只有一个的情况下,只能出现在参数列表的最后面 #fun1(name="lisi",30) #SyntaxError: positional argument follows keyword argument def fun2(a,b,c): print(a,b,c) fun2(10,c=30,b=20) #总结: # 关键字参数出现在实参中 # 关键字参数要么出现在参数列表的末尾【一个或者多个】,要么全部是关键字参数 # 关键字参数的出现:形参可以不用保持一定的顺序 # 应用场景:Python内置的功能 print()
1.3默认参数
调用函数的时候,如果没有传递参数,则使用默认参数的默认值
注意:默认参数主要操作的是形参
代码演示:
#默认参数【default】 #1.默认参数如果不传参,则使用默认值,如果传参,相当于给形参重新赋值 def fun1(name,age=18): print(name,age) fun1("lisi",20) """ age = 18 age = 20 """ fun1("jack") #2,在使用默认参数的同时,也可以使用关键字参数 fun1(name="abc",age=15) fun1(name="hello") #3.默认参数只能出现在参数列表的最后面,和关键字参数是类似的 def fun2(num1=10,num2=20): #SyntaxError: non-default argument follows default argument print(num1,num2) fun2() fun2(11)
1.4不定长参数【可变参数】
可以处理比声明的时候更多的参数 * **
代码演示:
#不定长参数 #1.* #注意1:*被当做tuple处理,形参的变量名其实就相当于一个元组的引用 #注意2:传参的时候,实参可以根据需求传任意数量和任意类型的数据 def fun1(*num): print(num) print(type(num)) fun1(10) fun1(10,20,30,40) fun1(38,45,True,"abc") #注意3:不定长参数只能出现在参数列表的最后面,而且只能出现一个 def fun2(num1,num2,*num3): for num in num3: print(num) fun2(10,20,30,50,54,5) #注意4;可以在实参部分传一个元组,但是,元组被当做了一个整体,形成了二维元组 def fun3(*a): print(a) fun3((3,53,5,4)) tuple1 = (3,53,5,4) fun3(tuple1) #2.**:被当做字典处理,变量名相当于字典名 def fun4(**args): print(args) print(type(args)) """ {'x': 1, 'y': 2} <class 'dict'> """ #fun4(10,20,30) #注意:如果行参列表中出现了**,实参的传递必需以key=value的方式传参 fun4(x=1,y=2) #类似于关键字参数,但是关键字参数必须和形参中的参数名保持一致, #在**中,实参的参数名可以任意定义,相当于给字典中添加键值对 #3.混合使用 def fun5(*num1,**num): print(num,num1) #分别被识别成了元组和字典 #fun5(23,4,35,35,name="zhangsan",age=10) #注意:*和**混合使用的时候,**必须出现在形参列表的最后面 #fun5(name="zhangsan",age=10,23,4,35,35)
2.函数的返回值
return的使用
作用:a.结束函数 b.将一个函数运算的结果返回
注意:函数的返回值在函数中不是必须存在的,具体的需求
代码演示:
#return的使用 #1.返回一个数据 格式:return 数据 #需求:求任意两个数的和 def myAdd(num1,num2): total = num1 + num2 return total #print("hello") #注意1:return表示结束函数,无法执行return语句之后的其他语句 #注意2;函数的返回值谁调用,返回给谁【返回给调用者】 result = myAdd(10,20) print(result) print(myAdd(1,2)) def test(): num = 10 print(test()) #2.返回多个数据,格式:return 数据1,数据2.。。。 #注意:多个数据被返回之后,当做元组进行处理 def test1(a,b,c): return a,b,c print(test1("abc",10,True)) #('abc', 10, True) #3.在分支语句中使用return #注意:每个分支下的return语句不是必需的,如果每个分支都有return,返回的数据类型可以不一致 #需求;输入两个数,。比较两个数的大小,输出较大的一个 def compare(a,b): if a > b: return a elif a < b: return b else: return True print(compare(10,20)) #4.return后面没有任何数据:只有一个作用,结束函数,返回值相当于是None def test2(a,b): if a > b: return print(test2(12,45)) #break和return的区别 def test3(): for i in range(5): print(i) if i == 3: #break #表示结束循环 return #表示结束函数 print("over") test3()
总结:
自定义函数,需要关注的问题
a.是否需要设置参数【如果有未知项参与运算】
b.是否需要设置返回值【函数运算的结果是不是需要在函数外部使用】
c.但凡涉及到功能,尽量封装函数
函数练习
代码演示:
""" 2.已知字符串 a = "aAsmr3idd4bgs7Dlsf9eAF",要求如下 a.请将a字符串的大写改为小写,小写改为大写 b.请将a字符串的数字取出,并输出成一个新的字符串 c.请统计a字符串出现的每个字母的出现次数(忽略大小写,a与A是同一个字母),并输出成一个字典。 例 {'a':4,'b':2} d.输出a字符串出现频率最高的字母 e.请判断 'boy'里出现的每一个字母,是否都出现在a字符串里。如果出现,则输出True,否则,则输 出False 3.输入一个字符串,压缩字符串如下aabbbccccd变成a2b3c4d1 """ a = "aAsmr3idd4bgs7Dlsf9eAF" def stringOperation1(s): newStr = s.swapcase() return newStr stringOperation1(a) def stringOperation2(s): newStr = "" for ch in s: if ch.isdigit(): newStr += ch return newStr def stringOperation3(s): s = s.lower() dict1 = {} for ch in s: if ch not in dict1: dict1[ch] = 1 else: dict1[ch] += 1 return dict1 def stringOperation4(s): #第一步;使用stringOperation3获取到的字典,获取value的最大值 dict2 = stringOperation3(s) print(dict2) max = 0 for value in dict2.values(): if value > max: max = value #第二步:将value的最大值和字典中的value进行比对,如果相等,则获取对应的key for key,value in dict2.items(): if value == max: print(key) stringOperation4(a) def stringOperation5(s): """ list1 = [1,2,3,4,5] set1 = set(list1) set1.update([4]) print(set1) """ #将字符串转换为集合 set1 = set(s) print(set1) search = "boy" set1.update(search) return len(set(s)) == len(set1) print(stringOperation5(a)) #3.输入一个字符串,压缩字符串如下aabbbccccd变成a2b3c4d1 def stringOperation6(s): dict2 = stringOperation3(s) newStr = "" for key,value in dict2.items(): newStr += key newStr += str(value) return newStr print(stringOperation6("aabbbccccd"))
3.匿名函数
本质:lambda表达式
特点:
a.lambda只是一个表达式,比def定义的函数简单
b.将匿名函数赋值给一个变量,然后使用变量调用函数
c.将有限的逻辑封装到lambda表达式中,一般用来实现比较 简单的需求
d.lambda拥有自己的命名空间,而且不能访问自有参数列表之外的变量
语法:lambda 参数列表:函数体
#匿名函数 #需求:求两个数的和 def total(num1,num2): return num1 + num2 print(total(10,20)) #注意:匿名函数本质是一个表达式,并没有名字,想要被调用,只能赋值给一个变量,然后使用这个变量调用函数【变量当做函数名使用】 result = lambda num1,num2:num1 + num2 print(result(10,20)) #特殊情况 #匿名函数也可以使用关键字参数进行参数传递 g = lambda x,y:x ** 2 + y ** 2 print(g(2,3)) print(g(x=2,y=3)) #匿名函数也可以使用默认参数 g = lambda x = 0,y = 0:x ** 2 + y ** 2 print(g()) print(g(2,3)) print(g(2)) print(g(y=3)
4.空函数和主函数
4.1空函数
一个什么功能都没有实现的函数,借助于pass语句
代码演示:
#空函数 def test(): pass test()
4.2主函数【main函数】
每个程序的入口
代码演示:
#模块中使用 if __name__ == "__main__": test()
三、函数的特殊使用【掌握】
1.变量可以指向函数
代码演示:
#1.变量指向函数 #abs() print(abs(-10)) #10 print(abs) #<built-in function abs> #a.abs(-10)是函数调用,abs是函数本身 #想要获得函数调用的结果,可以将结果赋值给一个变量 x = abs(-10) print(x) #10 y = abs print(y) #<built-in function abs> #b.函数本身也可以赋值给一个变量【变量指向函数】 print(y(-10)) #c。如果一个变量指向了一个函数,则可以通过该变量调用函数【变量名就是函数名】
2.函数名就是变量名
代码演示:
#2.函数名就是一个变量名 #abs():可以将函数名abs看成一个变量,它指向一个可以计算绝对值的函数 【num = 10】 #对abs重新赋值 abs = 10 #print(abs(-10)) #注意:不管是系统内置的功能,还是自定义的函数,函数名都是一个变量,指向了一个指定的函数,所以变量名尽量不要和函数名重名 #list = 100 list1 = list((54,54,654)) print(list1)
3.函数作为参数使用
代码演示:
#3.函数可以作为参数使用 #变量可以指向函数,函数的参数可以接收变量,那么一个函数可以接收另外一个函数作为参数,这种函数称为高阶函数 def test(x,y,f): return f(x) + f(y) print(test(10,-20,abs)) #x = 10 y = -10 f = abs f(-10) #注意:函数作为参数使用的时候,也需要遵循传参的规则 def hello(a): print("hello world") def show(f): #相当于调用的是hello函数 f(10) show(hello)
四、偏函数【了解】
代码演示:
import functools #偏函数 #作用:通过设定参数的默认值,可以减低函数的调用难度,而偏函数也可以做到这一点 #概念:对函数形式参数做一些控制的函数被称为偏函数 #注意:偏函数一般不需要自己定义,直接使用 #int(x) :将x转换为整型,当x为字符串时,默认按照十进制输出 #有一个默认参数base,默认值是10 print(int("123")) #123 #print(int("abc123")) print(int("123",base=10)) print(int("123",base=8)) #83 print(int("110",base=2)) #6 #需求:如果需要大量输出二进制 print(int("11010",base=2)) print(int("101010",base=2)) print(int("101110",base=2)) """ def int2(x,base=2): return int(x,base) print(int2("11010")) print(int2("101010")) print(int2("101110")) """ #要实现上面的需求,系统提供了功能:functools.partial(_) #偏函数:对于一个现成的函数,想要更改函数参数的默认值,生成一个新的函数,。被生成的函数被称为偏函数 #参数1;函数名 参数2:默认参数 int2 = functools.partial(int,base=2) print(int2("11010")) print(int2("101010")) print(int2("101110")) print((int2("10100",base=10))) print(int("10101",base=2))
五、闭包
如果在一个函数的内部定义了另外一个函数,外面的函数叫做外部函数,里面的函数叫做内部函数
在一个函数的内部定义了另外一个函数,并且外部函数的返回值是内部函数的引用,这样就构成了闭包
代码演示:
#外部函数 #1. def outerFunc(): #内部函数 def innerFunc(): print("hello") return innerFunc r = outerFunc() #r = innerFunc print(r) #<function outerFunc.<locals>.innerFunc at 0x000001D0BEF26510> r() #2. #outer是外部函数,a和b都是外部函数的临时变量 def outer(a): b = 10 def inner(): #在内部函数中,可以访问外部函数的临时变量 print(a + b) return inner #print(a,b) #NameError: name 'a' is not defined #调用;r1中保存了外部函数的返回值,也就是inner的引用【变量】, r1 = outer(4) #r1= inner #r1()相当于是调用了inner函数 r1() #闭包的应用场景:在Python中,装饰器
六、列表生成式和生成器
1.列表生成式
List Comprehensions,是Python内置的用来生成列表的生成式
range():
代码演示:
r = range(1,11) print(type(r)) #<class 'range'> print(list(r)) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(list(range(1,20,3))) #需求:生成一个列表,[1,4,9,16,25,36] l = [] for x in range(1,7): l.append(x * x) print(l) #[1, 4, 9, 16, 25, 36] #列表生成式 #格式:[生成的元素规律 for循环 判断条件] #1 l1 = [x * x for x in range(1,7)] print(l1) #[1, 4, 9, 16, 25, 36] #2.使用if判断[4,16,36,64,100] l2 = [x * x for x in range(1,11) if x % 2 == 0] print(l2) #3.使用嵌套for循环,生成的列表被称为全排列 l3 = [m + n for m in "ABC" for n in "XYZ"] print(l3) """ for m in "ABC": for n in "XYZ": """ #4。for循环可以同时使用两个或者多个变量 d = {"x":"a","y":"b","z":"c"} for k,v in d.items(): print(k,"=",v) l4 = [k + "=" + v for k,v in d.items()] print(l4) #1.将一个列表中的所有的字符改为小写,生成 一个新的列表 l1 = ["Hello","ABc","fdhf","YU"] newList = [] for element in l1: newList.append(element.lower()) newList1 = [element.lower() for element in l1]
2.生成器
generator
作用:为了解决当快速的生成一批数据,瞬间占用过大的内存
工作原理:生成较大数据的时候,将数据存储到生成器中,当需要数据的时候,去到生成器中获取
定义生成器有两种方式:
a.将列表生成式中的[]换成(),就是一个生成器
b.通过函数和yield【让步】生成
注意:生成器可以通过next()遍历其中的元素
代码演示:
#1. l1 = [x for x in range(1,6)] #列表生成式 l2 = (x for x in range(1,6)) #生成器 print(type(l1)) #<class 'list'> print(type(l2)) #<class 'generator'> #生成器可以使用for循环进行遍历 """ for i in l2: print(i) """ #通过调用next()获取生成器中的元素 print(next(l2)) print(next(l2)) print(next(l2)) print(next(l2)) print(next(l2)) #使用next获取生成器中的元素,当所有的元素被获取完成之后,继续调用next,则会出现StopIteration错误【异常】 #print(next(l2)) """ 1 2 3 4 5 """ print("~~~~~") #2. def test(n): for x in range(1,n + 1): yield x #暂停 print(x) tt = test(5) print(tt) #<generator object test at 0x000001A36A4A9200> #print(next(tt)) for i in tt: print(i) """ 1 1 2 2 3 3 4 4 5 5 总结:每次执行到yield的时候,则暂停代码的执行,将yield后面的值返回,代码停止 下次遍历生成器的时候【for和next】,函数生成器中的代码接着原来暂停的位置继续向下执行 """