Python函数
函数
(1)函数的含义:
功能 (包裹一部分代码 实现某一个功能 达成某一个目的)
(2)函数特点:
可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
(3)函数基本格式
# 函数的定义 def func(): code1.... code2.... # 函数的调用 func()
(4)函数命名
""" 函数的命名 字母数字下划线,首字符不能位数字 严格区分大小且,且不能使用关键字 函数命名有意义,且不能使用中文 驼峰命名法: (1)大驼峰命名法:每个单词的首字符大写 (一般在类中起名用这样的方式, 推荐) mycar => MyCar (2)小驼峰命名法:除了第一个单词首字符不用大写之外,剩下首字符都大写 (函数中的命名) mycar => myCar """
函数参数 : 函数运算时需要的值
(1)函数参数概念及分类
函数参数:调用时需要传递的数据.
函数参数大类分为形参和实参:
形参意思: 函数定义时的参数
实参意思: 函数调用时的参数
形实关系:函数调用时,形参和实参个数需要一一对应
形参种类: 普通参数(位置参数),默认参数,普通收集参数,命名关键字参数,关键字收集参数
实参种类: 普通实参,关键字实参
# 1.普通参数 """ 函数的定义处,普通形参 """ def small_start(hang,lie): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 函数的调用出为实参 small_start(3,8) # 2. 默认形参 hang,lie 在函数定义处给与默认值 """ 如果给与实参,那么就使用实际参数, 如果没给实参,那么就使用参数的默认值 """ def small_start(hang=10,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 3. 普通形参 + 默认形参 """默认形参必须写在普通形参的后面,语法上有要求""" # 函数的定义处 def small_start(hang,lie=10): # def small_start(hang,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # (4) 关键字实参 """ (1)如果使用关键字实参进行函数调用,实参的顺序无所谓 (2)如果定义时是普通形参,调用时是关键字实参, 那么这个参数后面的所有调用方式都需要关键字实参进行调用 """ def small_start(hang,a,b,c,lie=10): # def small_start(hang,lie=10): i = 0 while i<hang: j = 0 while j<lie: # 打印星星 print("*",end="") j+=1 # 打印换行 print() i+=1 # 关键字实参 hang 和 lie small_start(lie = 12,hang = 12)
(2)收集参数:
普通收集参数:专门用于收集多余的普通实参,形成一个新的元组
语法:参数前面加* 例:*args(arguments)
# 计算任意长度的累加和 def my_sum(*args): total = 0 for i in args: total += i print(total) my_sum(1,2,3,4,5)
关键字收集参数:专门用于收集多余的关键字实参,形成一个新的字典
语法:参数前面加** 例:**kwargs(keword arguments)
# 拼接任意字符串 def func(**kwargs): strvara = "" strvarb = "" dictvar = {"stra":"1","strb":"2"} for k,v in kwargs.items(): if k in dictvar: strvara += dictvar[k] + ":" + v + "\n" else: strvarb += v + " " print(strvara) print(strvarb) func(stra="A",strb="B",strc="C")
(3)命名关键字参数:定义时放在*号后面的参数,调用时强制必须指定关键字实参才能调
语法:(*,x) x是命名关键字参数
# 命名关键字参数 # 方法一 def func(a,b,*,c,d): print(a,b) print(c,d) func(1,2,c=3,d=4) # 方法二 def func(*args,c,**kwargs): print(args) print(c) print(kwargs) func(1,2,3,4,a=1,b=2,c=3) # 方法三 def func(a,b,*,c=3): print(a,b) print(c) func(1,2,c=33) # 区别于默认形参 def func(a,b,c=3): print(a,b) print(c) func(1,2) func(1,2,c=33) func(1,2,33) # 关键字参数只能传关键字
(4)*和**的魔术用法:打包和解包
*和**,在函数的定义处,负责打包(把实参都收集过来,放在元组或字典中)
*和**,在函数的调用处,负责解包(把容器类型的数据,一个一个拿出来,进行传递)
# * def func(a,b,c): print(a,b,c) listvar = [1,2,3] func(*listvar) # ** def func(a,*,b,c,d): print(a) print(b,c,d) dictvar = {"b":2,"c":3,"d":4} func(1,**dictvar) """ 在字典的前面加上一个*号,默认只传递健 """ def func(a,b): print(a,b) dictvar = {"a":1,"b":2} func(*dictvar) # *字符串 def func(a,b): print(a,b) strvar = "12" func(*strvar)
(5)形参声明的位置顺序:
普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
(6)对于任意函数,都可以通过 def func(*args, **kw) 来获取所有参数
return
return返回值
为这个函数返回一个结果 (return返回值可有可无 按照需求选择)
注意:执行return语句之后,函数执行结束
""" return 自定义返回值,如果没有写return ,默认返回None 功能:把值返回到函数的调用处; (1)return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数 (2)如果执行了return 语句,意味着函数终止,后面的代码不执行 """ # (1) return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数 def func(): # return 1 # return 3.14 # return 3+4j # return True # return [1,2,3] # return {"a":1,"b":2} pass res = func() # res ={"a":1,"b":2} print(res) # (2) 如果执行了return 语句,意味着函数终止,后面的代码不执行 def func(): print(1) return print(2) res = func() print(res) def func(): for i in range(5): if i == 3: return i print(i) res = func() # (3) 计算器示例 def calc(sign, num1, num2): if sign == "+": res = num1 + num2 elif sign == "-": res = num1 - num2 elif sign == "*": res = num1 * num2 elif sign == "/": if num2 == 0: return "除数不能为零" res = num1 / num2 return res res = calc("+", 1, 1) res = calc("-", -1, 90) res = calc("*", 52, 10) res = calc("/", 52, 10) res = calc("/", 5200, 10) print(res)
__doc__或者help查看文档
# __doc__ help(print) res = print.__doc__ print(res) # 自定义函数文档 def defined_word(): """ 功能:自定义函数文档 参数: :return: None """ print("自定义函数文档") # 方法一 res = defined_word.__doc__ print(res) # 方法二 help(defined_word)
内置函数
abs 绝对值函数
>>> res = abs(-90.7) >>> res 90.7 >>>
round 四舍五入 (n.5 n为偶数则舍去 n.5 n为奇数,则进一!)
>>> print(round(2.5)) 2 >>> print(round(3.5)) 4 >>>
sum 计算一个序列得和
>>> tuplevar = (1,2,3,4,5) >>> print(sum(tuplevar)) 15 >>>
max 获取一个序列里边的最大值
min 获取一个序列里边的最小值
>>> listvar = [11,88,66,33,77] >>> print(max(listvar)) 88 >>> print(min(listvar)) 11 >>> listvara = sorted(listvar) >>> listvara [11, 33, 66, 77, 88] >>> # 最大值 ... >>> print(listvara[-1]) 88 >>> # 最小值 ... >>> print(listvara[0]) 11 >>>
>>> # 获取一个序列里面的最小值,key=自定义函数 ... >>> listvar = [("a",88),("b",66),("c",99)] >>> def func(n): ... return n[1] % 10 ... >>> res = min(listvar,key=func) >>> print(res) ('b', 66) >>>
pow 计算某个数值的x次方
>>> # 第三个参数时可选项,如果存在,前两个平方后和第三个取余 ... >>> print(pow(2,3)) 8 >>> print(pow(2,3,3)) 2 >>>
range 产生指定范围数据的可迭代对象
>>> for i in range(9,0,-2): ... print(i) ... 9 7 5 3 1 >>>
bin 将10进制数据转化为二进制
oct 将10进制数据转化为八进制
hex 将10进制数据转化为16进制
>>> print(bin(6)) 0b110 >>> print(oct(9)) 0o11 >>> print(hex(16)) 0x10 >>>
chr 将ASCII编码转换为字符
ord 将字符转换为ASCII编码
>>> print(chr(97)) a >>> print(ord("A")) 65 >>>
eval 将字符串当作python代码执行
exec 将字符串当作python代码执行(功能更强大)
>>> strvar = "print(123)" >>> res = eval(strvar) 123 >>> print(res) # 返回值没有意义 None >>> >>> strvar = 'course = "python"' >>> res = eval(strvar) # 声明变量,eval不允许 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1 course = "python" ^ SyntaxError: invalid syntax >>> >>> strvar = 'course = "python"' >>> res = exec(strvar) >>> print(course) python >>> print(res) None >>>
>>> strvar = """ ... for i in range(5): ... print(i) ... """ >>> exec(strvar) 0 1 2 3 4 >>>
repr 不转义字符输出字符串
>>> strvar = "D:\note" >>> print(strvar) D: ote >>> print(repr(strvar)) 'D:\note' >>>
input 接受输入字符串
>>> res = input("Please input username>>>") Please input username>>>admin >>>
hash 生成哈希值
>>> strvara = "password" >>> strvarb = "password" >>> print(hash(strvara)) -8671913786014747281 >>> print(hash(strvarb)) -8671913786014747281 >>>
参数练习
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
以上两个函数 打印结果
#(一)
f1(1, 2)
f1(1, 2, c=3)
f1(1, 2, 3, 'a', 'b')
f1(1, 2, 3, 'a', 'b', x=99)
f2(1, 2, d=99, ext=None)
#(二)
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)
#(三)
myargs = (1, 2, 3)
mykw = {'d': 88, 'x': '#'}
f2(*myargs, **mykw)
#(四)
def f1(a, b, c=0, *args,d,**kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
print(d)
f1(1,2,3, 'a', 'b',d=67, x=99,y=77)
>>> def f1(a,b,c=0,*args,**kw): ... print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw) ... >>> def f2(a,b,c=0,*,d,**kw): ... print('a=',a,'b=',b,'c=',c,'d=',d,'kw=',kw) ... >>> f1(1,2,c=3) a= 1 b= 2 c= 3 args= () kw= {} >>> f1(1,2,3,'a','b') a= 1 b= 2 c= 3 args= ('a', 'b') kw= {} >>> f1(1,2,3,'a','b',x=99) a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99} >>> f2(1,2,d=99,ext=None) a= 1 b= 2 c= 0 d= 99 kw= {'ext': None} >>> args=(1,2,3,4) >>> kw={'d':99,'x':'#'} >>> f1(*args,**kw) a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': '#'} >>> myargs=(1,2,3) >>> mykw={'d':88,'x':'#'} >>> f2(*myargs,**mykw) a= 1 b= 2 c= 3 d= 88 kw= {'x': '#'} >>> def f1(a,b,c=0,*args,d,**kw): ... print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw) ... print(d) ... >>> f1(1,2,3,'a','b',d=67,x=99,y=77) a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99, 'y': 77} 67
python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限
1.函数名是个特殊的变量,可以当做变量赋值
2.函数名可以作为容器类型数据的元素
3.函数名可以作为函数的参数
4.函数名可作为函数的返回值
>>> # 1.函数名是个特殊的变量,可以当做变量赋值 ... def func(): ... print("函数名可以当成变量赋值") ... >>> abc = 45 >>> abc = func >>> print(abc) <function func at 0x00000209F87256A8> >>> abc() 函数名可以当成变量赋值 >>> >>># 2.函数名可以作为容器类型数据的元素 >>> def func1(): ... print(1) ... >>> def func2(): ... print(2) ... >>> listvar = [func1,func2] >>> print(listvar) [<function func1 at 0x00000209F87257B8>, <function func2 at 0x00000209F8725730>] >>> for i in listvar: ... i() ... 1 2 >>> >>> # 3.函数名可以作为函数的参数 ... >>> def func1(func): ... func() ... >>> def func2(): ... print('func2') ... >>> func1(func2) func2 >>> >>> # 4.函数名可以作为函数的返回值 ... >>> def func1(func): ... return func ... >>> def func2(): ... print('func2') ... >>> res = func1(func2) >>> print(res) <function func2 at 0x00000209F8725840> >>> res() func2 >>>
__doc__或者help查看文档
作用域:作用范围
命名空间 : 划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系).一共三种.
(1)内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长
(2)全局命名空间:文件运行时创建,直到解释器运行结束,生存周期较长
(3)局部命名空间:函数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短
命名空间的提出是为了划分和控制变量是否可见,以及生存周期的长短.
命名空间 创建顺序:(了解)
python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
命名空间 销毁顺序:(了解)
函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
全局变量 与 局部变量 及 其关键字的使用
局部变量:函数内部的变量是局部变量,作用域仅在函数内部可见(局部命名空间)
全局变量:函数外部的变量是全局变量,作用域横跨整个文件(全局命名空间)
# 局部变量的获取 与 修改 def func(): a = 15 # 获取局部变量 print(a) # 修改局部变量 a = 17 print(a) func() # print(a) error a局部变量值限定在函数内部使用; # 全局变量的获取 与 修改 b = 100 # 获取全局变量 print(b) # 修改全局变量 b += 200 print(b)
内置函数:内建命名空间
global :关键字:声明全局变量获修改全局变量
# 在函数内部可以直接获取全局变量,但是不能直接修改 # 用global关键字,修改全局变量 c = 50 def func(): global c print(c) c = 60 print(c) func() print(c) # 在函数内部可以直接定义一个全局变量 def func(): global d d = 90 func() print(d)
nonlocal :关键字:修改局部变量(当前函数上一层的局部变量)
# (1) nonlocal 只能用来修改局部变量 a = 90 def func(): # nonlocal a error a = 80 print(a) func() # (2) nonlocal 会不停的寻找上一层空间所对应的值,拿来修改 """通过LEGB原则,可以获取到上一层空间的值,只能单纯的获取,不能直接修改 如果想要修改 通过nonlocal 加以修饰. """ def outer(): a = 20 def inner(): nonlocal a print(a) a += 1 print(a) inner() outer() # (3) 如果上一层找不到,继续向上寻找,再也找不到了,直接报错; nonlocal 只能修饰局部变量 a = 100 def outer(): a = 100 def inner(): # a = 110 def smaller(): nonlocal a a += 10 # print(a) smaller() print(a,"<=1=>") inner() print(a,"<=2=>") outer() # (4) 不通过nonlocal 是否可以改变局部变量? 可以! 需要使用列表进行操作; def outer(): lst = [100,101,102] def inner(): lst[0] += 1 inner() print(lst) outer()
locals() :返回字典,获取当前作用域的所有内容
如果在函数里:获取locals()调用之前,该作用域出现的内容
如果在函数外:获取locals()打印返回值之前,该作用域出现的内容
# 当前作用域在全局范围 a = 1 b = 2 res = locals() c = 3 print(res) # 当前作用域在局部范围 zz = 90 def func(): d = 4 f = 5 res = locals() g = 6 print(res) func()
globals() :返回字典,获取全局作用域的所有内容
如果在函数里: 获取globals()调用之前,全局作用域出现的内容
如果在函数外: 获取globals()打印返回值之前,全局作用域出现的内容
""" globals 无论在函数内外,都只获取全局作用域当中的所有内容 如果globals在函数外:所获取的是globals(),打印返回值之前的所有内容 如果globals在函数内:所获取的是globals(),调用之前所有内容 """ # 当前作用域在全局范围 a = 1 b = 2 res = globals() c = 3 print(res) # 当前作用域在局部范围 aa = 11 bb = 22 def func(): d =1 f = 2 res = globals() z = 3 print(res) cc = 33 func() #res = globals() dd = 4 # globals 动态的创建全局变量 """ globals() 返回的是系统的字典,只需要在字典里面添加键值对,就可以创建全局变量 字典中的键 就是变量名 字典中的值 就是变量所指代的值 """ dic = globals() print(dic) dic["strvar"] = "abc" print(strvar) # 创建p1~p5 5个全局变量 def func(): dic = globals() for i in range(1,6): # p1 ~ p5 5个键 dic["p%d" % (i)] = i func() print(p1) print(p2) print(p3) print(p4) print(p5)
LEGB原则(即就近原则找变量)
找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
内部函数
(1)内部函数可以直接在函数外部调用么
(2)调用外部函数后,内部函数可以在函数外部调用吗
(3)内部函数可以在函数内部调用吗
(4)内部函数在函数内部调用时,是否有先后顺序
>>> # 函数的嵌套 ... >>> def outer(): ... def inner(): ... def smaller(): ... print(id) ... print('small func') ... smaller() ... inner() ... >>> outer() <built-in function id> small func >>>
闭包
获取闭包函数使用的变量 __closure__ , cell_contents
闭包的定义:
内函数使用外函数的局部变量,并且外函数将内函数返回出来的方法叫闭包,
返回的内函数叫 闭包函数.
闭包的特点:
内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期
(实际内存给它存储了这个值,暂时不释放)
""" 内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长了该变量的生命周期 """ def outer(val): def inner(num): return num + val return inner func = outer(10) res = func(5) # func = inner() = num + val = 10 + 5 = 15 print(res)
闭包的意义:
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
""" 闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问. 模拟一个鼠标点击计数功能: """ clicknum = 0 def clickfunc(): global clicknum clicknum += 1 print(clicknum) # 模拟点击操作,点击一次就调用一次 clickfunc() clickfunc() clickfunc() clickfunc() clickfunc() clicknum = 100 clickfunc() # 用闭包函数来进行改造 def clickfunc(): x = 0 def func(): nonlocal x x +=1 print(x) return func clickfunc2 = clickfunc() clickfunc2() # clickfunc2() = func() clickfunc2() clickfunc2() clickfunc2() clickfunc2() x = 100 clickfunc2()
匿名函数
lambda 表达式:用一句话来表达只有返回值的函数
好处:简洁,方便,定义函数快速简单
语法:lambda 参数 : 返回值
>>> # 1.无参数的lambda表达式 ... >>> def func(): ... return 123 ... >>> res = func() >>> print(res) 123 >>> func = lambda:123 >>> res = func() >>> print(res) 123 >>> >>> # 2.有参数的lambda表达式 ... >>> def func(n): ... return type(n) ... >>> res = func('123') >>> print(res) <class 'str'> >>> func = lambda n : type(n) >>> res = func('123') >>> print(res) <class 'str'> >>> >>> # 3.带有条件判断的lambda表达式 """ 三元运算: 真值 if 条件表达式 else 假值 如果条件表达式成立,执行真值 如果条件表达式不成立,执行假值 """ >>> def func(n): ... if n % 2 == 0: ... return "偶数" ... else: ... return "奇数" ... >>> func(11) >>> n = 11 >>> func = "偶数" if n % 2 == 0 else "奇数" >>> func '奇数' >>> >>> # 计算参数中的最大值 ... >>> def func(m,n): ... if m > n: ... return m ... else: ... return n ... >>> print(func(11,33)) 33 >>> func = lambda m,n : m if m > n else n >>> print(func(11,33)) 33 >>>
递归函数
递归函数:自己调用自己的函数 (递:去 归:回 一去一回是递归)
(1)每调用一次函数,就是开辟一个栈帧空间的过程
每结束一次函数,就是释放一个栈帧空间的过程
递归函数就是不停的开辟栈帧空间和释放栈帧空间的过程
(2)回的过程有两种触发时机:
(1)当最后一层函数全部执行完毕,触发回的过程,回到上一层函数调用处
(2)当遇到return 返回值的时候,触发回的过程,回到上一层函数调用处
>>> def recursion(n): ... print("session01>>>",n) ... if n > 0: ... recursion(n-1) ... print("session02>>>",n) ... >>> recursion(5) session01>>> 5 session01>>> 4 session01>>> 3 session01>>> 2 session01>>> 1 session01>>> 0 session02>>> 0 session02>>> 1 session02>>> 2 session02>>> 3 session02>>> 4 session02>>> 5 >>> >>> # 计算n的阶乘 ... >>> def factorial(n): ... if n <= 1: ... return 1 ... return n * factorial(n-1) ... >>> res = factorial(5) >>> print(res) 120 >>>
如果我们计算fact(5)
,可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
内存栈区堆区(了解内容)
单独讲栈堆是数据结构
栈:后进先出的一种数据结构
堆:排序后的一种树状数据结构
栈区堆区是内存空间
栈区:按照后进先出的数据结构(栈),无论创建或销毁都是自动为数据分配内存,释放内存
(系统自动做的)
堆区:按照排序后的树状数据结构(堆),可优先取出必要数据,无论创建或销毁都是手动分配内存,释放内存(程序员手动做的)
--内存中的栈区 : 自动分配 自动释放
--内存中的堆区 : 手动分配 手动释放
运行程序时在内存中执行,会因为数据类型的不同而在内存的不同区域运行
因不同语言对内存划分的机制不一,但大体来讲,有如下四大区域
--栈区: 分配局部变量空间.
--堆区: 是用于手动分配程序员申请的内存空间.
--静态区(全局栈区): 分配静态变量,全局变量空间.
--代码区(只读区,常量区): 分配常量和程序代码空间的.
栈区 堆区 静态区 代码区 都是内存中的一段空间
迭代器
迭代器:能被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator 迭代器是对象)
特征:迭代器会生成惰性序列,它通过计算把值依次的返回,一边循环一边计算而不是一次性得到所有数据
优点:需要数据的时候,一次取一个,可以大大节省内存空间.而不是一股脑的把所有数据放进内存.
--Iterable可迭代的 Iterator迭代器
惰性序列:没有一次性的把所有数据都放在序列中,而是遍历一个放一个,这样的序列
1.可迭代对象。
如果一个数据类型其中的成员包含了__iter__方法,这个数据类型就是可迭代对象
dir 这个函数可以获取该数据类型的成员结构
>>> setvar ={1,2,'a','b'} >>> setvar {1, 2, 'b', 'a'} >>> for i in setvar: ... print(i) ... 1 2 b a >>> res = dir(setvar) >>> res ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'] >>>
2.迭代器
for循环在迭代数据的时候,内部先转化为迭代器,然后通过next方法来进行调用
变成迭代器:
(1)iter (2)__iter__()
>>> setvar ={1,2,'a','b'} >>> res = iter(setvar) >>> res <set_iterator object at 0x00000135A70DB8B8> >>> ret = setvar.__iter__() >>> ret <set_iterator object at 0x00000135A70DB900> >>>
遍历迭代器
(1)next (2)__next__()
>>> setvar ={1,2,'a','b'} >>> res = iter(setvar) >>> ret = next(res) >>> ret 1 >>> ret = next(res) >>> ret 2 >>> ret = next(res) >>> ret 'b'
判断可迭代对象
>>> setvar ={1,2,'a','b'} >>> res = iter(setvar) >>> print("__iter__" in dir(setvar)) True >>>
判断迭代器
(1)含有__iter__和__next__两个方法,该数据类型就是迭代器
>>> setvar ={1,2,'a','b'} >>> res = iter(setvar) >>> print("__iter__" in dir(res) and "__next__" in dir(res)) True >>>
(2)from collections import Iterator,Iterable
>>> from collections import Iterator,Iterable >>> listvar = [1,2,3,4] >>> # 是否是一个迭代器 ... >>> res = isinstance(listvar,Iterator) >>> res False >>> # 是否是可迭代对象 ... >>> res = isinstance(listvar,Iterable) >>> res True >>>
迭代器是可迭代对象
可迭代对象不一定是迭代器
range 是 可迭代对象
>>> res = isinstance(range(10),Iterator) >>> res False >>> res = isinstance(range(10),Iterable) >>> res True >>>
range 和 迭代器 能够产生惰性序列
在调用时,超出了原有的数据个数,会直接越界报错
>>> it = iter(range(3)) >>> print(next(it)) 0 >>> print(next(it)) 1 >>> print(next(it)) 2 >>> print(next(it)) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
遍历
通过for和next配合使用
>>> it = iter(range(5)) >>> for i in range(3): ... res = next(it) ... print(res) ... 0 1 2 >>>
通过for一次性遍历迭代器中所有数据
>>> it = iter(range(5)) >>> for i in it: ... print(i) ... 0 1 2 3 4 >>>
高阶函数
高阶函数:能够把函数当成参数传递的就是高阶函数
map
map(func,iterable)
功能:
把iterable里面所有数据 一一的放进到func这个函数中进行操作 ,把结果扔进迭代器
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值:
返回最后的迭代器
例1:["1","2","3","4"] ==> [1,2,3,4]
常规方法
>>> listvar = ["1","2","3","4"] >>> listvara = [] >>> for i in listvar: ... res = int(i) ... listvara.append(res) ... >>> listvara [1, 2, 3, 4] >>>
使用map
>>> listvar = ["1","2","3","4"] >>> from collections import Iterator,Iterable >>> it = map(int,listvar) >>> print(isinstance(it,Iterator)) True >>> print(next(it)) 1 >>> print(next(it)) 2 >>> print(next(it)) 3 >>> print(next(it)) 4 >>> # 使用for进行调用 ... >>> it = map(int,listvar) >>> for i in it: ... print(i) ... 1 2 3 4 >>> # for配合next进行调用 ... >>> it = map(int,listvar) >>> for i in range(2): ... res = next(it) ... print(res) ... 1 2 >>> # 使用list强转成列表 ... >>> it = map(int,listvar) >>> lst = list(it) >>> lst [1, 2, 3, 4] >>>
例2:[1,2,3,4] ==> [3,6,9,12]
>>> listvar = [1,2,3,4] >>> listvara = [] >>> for i in listvar: ... res = i * 3 ... listvara.append(res) ... >>> listvara [3, 6, 9, 12] >>>
map
>>> listvar = [1,2,3,4] >>> def func(n): ... return n * 3 ... >>> it = map(func,listvar) >>> print(list(it)) [3, 6, 9, 12] >>>
例3:{97:"a",98:"b",99:"c"} ==> {"a":97,"b":98,"c":99}
>>> dictvar = {97:"a",98:"b",99:"c"} >>> dictvara = {} >>> res = dictvar.items() >>> res dict_items([(97, 'a'), (98, 'b'), (99, 'c')]) >>> # 反转字典中的键值对 ... >>> for k,v in res: ... dictvara[v] = k ... >>> dictvara {'a': 97, 'b': 98, 'c': 99} >>>
map自定义函数,需要一个参数,必须写一个返回值
>>> def func(n): ... dictvar = {97:"a",98:"b",99:"c"} ... for k,v in dictvar.items(): ... dictvara[v] = k ... return dictvara[n] ... >>> it = map(func,["a","b","c"]) >>> print(list(it)) [97, 98, 99] >>>
reduce
reduce(func,iterable)
功能:
先把iterable里面的前2个数据拿到func函数当中进行运算,得到结果,
在把计算的结果和iterable中的第三个数据拿到func里面进行运算,
依次类推 ,直到iterable里面的所有数据都拿完为止,程序结束
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值:
计算的最后结果
例1:[5,4,8,8] ==> 5488
>>> listvar = [5,4,8,8] >>> strvar = '' >>> for i in listvar: ... strvar += str(i) ... >>> print(strvar,type(strvar),int(strvar)) 5488 <class 'str'> 5488 >>>
方法二:
5 * 10 + 4 = 54
54 * 10 + 8 = 548
548 * 10 + 8 = 5488
>>> listvar = [5,4,8,8] >>> it = iter(listvar) >>> res1 = next(it) >>> res2 = next(it) >>> res = res1 * 10 + res2 >>> res 54 >>> for i in it: ... res = res * 10 + i ... >>> print(res,type(res)) 5488 <class 'int'> >>>
使用reduce进行改写
>>> from functools import reduce >>> listvar = [5,4,8,8] >>> def func(x,y): ... return x*10 + y ... >>> res = reduce(func,listvar) >>> print(res,type(res)) 5488 <class 'int'> >>>
例2:"789" ==> 789 不适用int强转的前提下完成
>>> strvar = "789" >>> def func(n): ... dictvar = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9} ... return dictvar[n] ... >>> def funca(x,y): ... return x*10 + y ... >>> it = map(func,strvar) >>> res = reduce(funca,it) >>> print(res,type(res)) 789 <class 'int'> >>>
sorted
sorted(iterable,reverse=False,key=函数)
功能:
对数据进行排序
参数:
iterable : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
reverse : 是否反转 默认为False 代表正序, 改成True 为倒序
key : 指定函数 内置或自定义函数
返回值:
返回排序后的数据
>>> # 默认从小到大排序 ... >>> listvar = [88,31,-90,0] >>> res = sorted(listvar) >>> res [-90, 0, 31, 88] >>> # 从大到小排序 ... >>> listvar = [88,31,-90,0] >>> res = sorted(listvar,reverse=True) >>> res [88, 31, 0, -90] >>>
列1:按照绝对值排序,使用内置函数
>>> listvar = [-99,-2,45,1] >>> res = sorted(listvar,key=abs) >>> res [1, -2, 45, -99] >>>
例2:按照余数排序,使用自定义函数
>>> def func(n): ... return n % 10 ... >>> listvar = (19,24,91,36) >>> res = sorted(listvar,key=func) >>> res [91, 24, 36, 19] >>> listvar (19, 24, 91, 36) >>>
filter
filter(func,iterable)
功能:
用来过滤的,如果func函数中返回True , 会将这个值保留到迭代器中
如果func函数中返回False , 会将此值舍弃不保留
参数:
func : 自定义函数
iterable : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
返回值:
返回处理后的迭代器
例1:保留偶数
基本写法
>>> listvar = [1,2,3,4,5,6,7,8,9] >>> for i in listvar: ... if i % 2 ==0: ... print(i) ... else: ... pass ... 2 4 6 8 >>>
filter写法
>>> def func(n): ... if n % 2 == 0: ... return True ... else: ... return False ... >>> it = filter(func,listvar) >>> print(list(it)) [2, 4, 6, 8] >>>
简洁写法
>>> func = lambda n:True if n % 2 == 0 else False >>> it = filter(lambda n : True if n % 2 == 0 else False,listvar) >>> print(list(it)) [2, 4, 6, 8] >>>
通过一行循环判断,遍历出一系列数据的方式是推导式
语法: val for val in Iterable (把想要的值写在 for的左侧)
里面是一行循环判断!根据套在推导式外层的符号判断具体是什么类型的推导式
推导式种类三种:
[val for val in Iterable] 列表推导式
{val for val in Iterable} 集合推导式
{a:b for a,b in iterable} 字典推导式
例1:生成一个列表 listvar=[1,2,3,4,5,6,7,8,9,10]
>>> listvar = [] >>> for i in range(1,11): ... listvar.append(i) ... >>> listvar [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>>
普通列表推导式
>>> listvar = [i for i in range(1,11)] >>> listvar [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> listvar = [i*2 for i in range(1,11)] >>> listvar [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] >>>
带有判断条件的列表推导式
基本写法
>>> listvar = [1,2,3,4,5,6,7,8,9] >>> listvara = [] >>> for i in listvar: ... if i % 2 == 1: ... listvara.append(i) ... >>> listvara [1, 3, 5, 7, 9] >>>
推导式写法
>>> listvar = [1,2,3,4,5,6,7,8,9] >>> listvara = [i for i in listvar if i % 2 == 1] >>> listvara [1, 3, 5, 7, 9] >>>
双循环列表推导式
>>> listvara = ["1","2","3"] >>> listvarb = ["a","b","c"] >>> listvar = [] >>> for i in listvara: ... for j in listvarb: ... strvar = i + ":" + j ... listvar.append(strvar) ... >>> listvar ['1:a', '1:b', '1:c', '2:a', '2:b', '2:c', '3:a', '3:b', '3:c'] >>> >>> listvar = [i + ":" + j for i in listvara for j in listvarb] >>> listvar ['1:a', '1:b', '1:c', '2:a', '2:b', '2:c', '3:a', '3:b', '3:c'] >>>
带有条件判断的双循环列表推导式
>>> listvara = ["1","2","3"] >>> listvarb = ["a","b","c"] >>> listvar = [] >>> for i in listvara: ... for j in listvarb: ... if listvara.index(i) == listvarb.index(j): ... strvar = i + ":" + j ... listvar.append(strvar) ... >>> listvar ['1:a', '2:b', '3:c'] >>> >>> >>> listvar = [i + ":" + j for i in listvara for j in listvarb if listvara.index(i) == listvarb.index(j)] >>> listvar ['1:a', '2:b', '3:c'] >>>
列表推导式,集合推导式,字典推导式的相关写法
(1)普通推导式
(2)带有判断条件的推到式
(3)多循环推到式
(4)带有判断条件的多循环推到式
集合推导式(去重)
>>> setvar = {15 if i % 2 == 1 else 16 for i in range(3)} >>> setvar {16, 15}
(1)enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
>>> from collections import Iterator,Iterable >>> listvar = [1,2,3,4] >>> it = enumerate(listvar) >>> print(it) <enumerate object at 0x000001D7FC53BAB0> >>> print(isinstance(it,Iterator)) True >>> print(list(it)) [(0, 1), (1, 2), (2, 3), (3, 4)] >>>
强制迭代器变成字典
>>> listvar = ["a","b","c"] >>> it = enumerate(listvar) >>> res = dict(it) >>> print(res) {0: 'a', 1: 'b', 2: 'c'} >>>
字典推导式变成字典
>>> listvar = ["a","b","c"] >>> it = enumerate(listvar) >>> dictvar = {k:v for k,v in it} >>> print(dictvar) {0: 'a', 1: 'b', 2: 'c'} >>> >>> it = enumerate(listvar,start=10) >>> dictvar = {k:v for k,v in it} >>> print(dictvar) {10: 'a', 11: 'b', 12: 'c'} >>>
(2)zip
zip(iterable, ... ...)
功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回: 迭代器
>>> listvara = ["1","2","3"] >>> listvarb = ["a","b","c"] >>> listvarc = ["e","f","g"] >>> it = zip(listvara,listvarb,listvarc) >>> print(list(it)) [('1', 'a', 'e'), ('2', 'b', 'f'), ('3', 'c', 'g')] >>>
dict强转迭代器变成字典
>>> listvara = ["1","2","3"] >>> listvarb = ["a","b","c"] >>> res = dict(zip(listvara,listvarb)) >>> print(res) {'1': 'a', '2': 'b', '3': 'c'} >>>
字典推导式
>>> dictvar = {k:v for k,v in zip(listvara,listvarb)} >>> print(dictvar) {'1': 'a', '2': 'b', '3': 'c'} >>>
元组推导式是生成器(generator)
元组推导式的返回值是一个生成器对象,简称生成器,生成器本质就是迭代器.
迭代器和生成器区别:
迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
生成器可以用两种方式创建:
(1)生成器表达式 (里面是推导式,外面用圆括号)
(2)生成器函数 (用def定义,里面含有yield)
yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
基本定义,返回生成器对象,简称生成器
>>> from collections import Iterator >>> generator_obj = (i for i in range(10)) >>> print(generator_obj) <generator object <genexpr> at 0x000001D7FC506570> >>> print(isinstance(generator_obj,Iterator)) True >>>
使用next方法调用
>>> res = next(generator_obj) >>> res 0 >>>
for配合next调用
>>> for i in range(5): ... res = next(generator_obj) ... print(res) ... 1 2 3 4 5
for循环遍历生成器
>>> for i in generator_obj: ... print(i) ... 6 7 8 9 >>>
生成器函数
1.基本语法
>>> def mygen(): ... print(1) ... yield 1 ... print(2) ... yield 2 ... print(3) ... yield 3 ... >>>
初始化生成器函数,返回生成器对象,调用完后会报错
>>> gen = mygen() >>> res = next(gen) 1 >>> res = next(gen) 2 >>> res = next(gen) 3 >>> res = next(gen) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
例1:
def mygen(): for i in range(100): yield "num:{:d}".format(i) # 初始化生成器函数 ,返回生成器对象,简称生成器 gen = mygen() for i in range(50): res = next(gen) print(res) for i in range(30): print(next(gen))
数据量大使用for进行遍历,会死循环
生成器send 与 yield from
send
next和send区别:
next 只能取值
send 不但能取值,还能发送值
send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
>>> def mygen(): ... print(1) ... res1 = yield 1 ... print(res1,"接受返回1") ... res2 = yield 2 ... print(res2,"接受返回2") ... >>> # 初始化生成器函数 ... >>> gen = mygen() >>> # 第一次无法给上一个yield发送数据,强制发送None ... >>> res = gen.send(None) 1 >>> res = gen.send(111) 111 接受返回1 >>> res = gen.send(222) 222 接受返回2 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
yield from : 将一个可迭代对象变成一个迭代器返回
>>> def mygen(): ... yield from [1,2,3] ... >>> gen = mygen() >>> res = next(gen) >>> res 1 >>> res = next(gen) >>> res 2 >>> res = next(gen) >>> res 3 >>>
斐波那契数列(用前两数相加得到第三个)
>>> def mygen(n): ... a,b = 0,1 ... i = 0 ... while i < n: ... yield b ... a,b = b,a+b ... i += 1 ... >>> gen = mygen(5) >>> for i in gen: ... print(i) ... 1 1 2 3 5 >>>
练习题:
(1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式
(2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"]
(3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中
(4).使用列表推导式 制作所有99乘法表中的运算
(5)#求M,N中矩阵和元素的乘积
M = [ [1,2,3],
[4,5,6],
[7,8,9] ]
N = [ [2,2,2],
[3,3,3],
[4,4,4] ]
=>实现效果1 [2, 4, 6, 12, 15, 18, 28, 32, 36]
=>实现效果2 [[2, 4, 6], [12, 15, 18], [28, 32, 36]]