day4 (迭代器、生成器、递归、面向过程、内置函数等)
一、迭代器
#迭代器:迭代的工具 #1 什么是迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值 # while True: # print('=====>') l=['a','b','c'] count=0 while count < len(l): print(l[count]) count+=1 # a # b # c #2 为什么要有迭代器? #对于序列类型:str,list,tuple,可以依赖索引来迭代取值, # 但是对于dict,set,文件,python必须为我们提供一种不依赖于索引的迭代取值的方式-》迭代器 #3 可迭代的对象(下列都是):obj.__iter__ name='egon' l=[1,2,3] t=(1,2,3) d={'name':'egon','age':18,'sex':'male'} s={'a','b','c'} f=open('a.txt','w',encoding='utf-8') # name.__iter__ # l.__iter__ # t.__iter__ # d.__iter__ # s.__iter__ # f.__iter__ #以上数据类型都有__iter__ 的方法 #4 迭代器对象(文件是):既有obj.__iter__ 方法又有 obj.__next__ 方法 # f.__iter__ # f.__next__ #总结: #1 可迭代对象不一定是迭代器对象 #2 迭代器对象一定是可迭代的对象 #3 调用obj.__iter__()方法,得到的是迭代器对象(对于迭代器对象,执行__iter__得到的仍然是它本身) d={'name':'egon','age':18,'sex':'male'} d_iter=d.__iter__() #可迭代对象调用后返回迭代器对象 f=open('a.txt','w',encoding='utf-8') f_iter=f.__iter__().__iter__().__iter__().__iter__() #迭代器对象调用返回的还是本身 print(f_iter is f) #True d={'name':'egon','age':18,'sex':'male'} d_iter=d.__iter__() print(d_iter.__next__()) #name print(d_iter.__next__()) #age print(d_iter.__next__()) #sex #print(d_iter.__next__()) #迭代器d_iter没有值了,就会抛出异常StopIteration #StopIteration # f=open('a.txt','r',encoding='utf-8') # print(f.__next__()) # print(f.__next__()) # print(f.__next__()) # print(f.__next__()) # f.close() l=['a','b','c'] l_iter=l.__iter__() print(l_iter.__next__()) #a print(l_iter.__next__()) #b print(l_iter.__next__()) #c #print(l_iter.__next__()) #StopIteration d={'name':'egon','age':18,'sex':'male'} d_iter=iter(d) #d_iter=d.__iter__() #len(obj) 等同于obj.__len__() while True: try: print(next(d_iter)) #print(d_iter.__next__()) except StopIteration: #判断抛出错误的类型 break # name # age # sex #for循环详解: #1、调用in后的obj_iter=obj.__iter__() #2、k=obj_iter.__next__() #3、捕捉StopIteration异常,结束迭代 d={'name':'egon','age':18,'sex':'male'} for k in d: print(k) # name # age # sex #总结迭代器的优缺点: #优点: #1、提供一种统一的、不依赖于索引的取值方式,为for循环的实现提供了依据 #2、迭代器同一时间在内存中只有一个值——》更节省内存, #缺点: #1、只能往后取,并且是一次性的 #2、不能统计值的个数,即长度 l = [1,2,3,4,5,6] l_iter = iter(l) print(len(l_iter)) #TypeError: object of type 'list_iterator' has no len()
二、生成器
#1 什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器 def func(): print('=====>1') yield 1 print('=====>2') yield 2 print('=====>3') yield 3 # # #生成器就是迭代器 g=func() print(g) #<generator object func at 0x102210fc0> res1=next(g) print(res1) # =====>1 # 1 res2=next(g) print(res2) # =====>2 # 2 res3=next(g) print(res3) # =====>3 # 3 #res4 = next(g) #StopIteration #yield的功能: #1、yield为我们提供了一种自定义迭代器对象的方法 #2、yield与return的区别1:yield可以返回多次值 #2:函数暂停与再继续的状态是由yield帮我们保存的 #模仿range def my_range(start,stop,step=1): while start < stop: yield start #start=1 start+=step #start=3 g=my_range(1,5,2) print(g) #<generator object my_range at 0x102210f10> for n in my_range(1,5,2): print(n) # 1 # 3 #小练习::tail -f access.log | grep '404' import time def tail(filepath): with open(filepath,'rb') as f: f.seek(0,2) while True: line=f.readline() if line: yield line else: time.sleep(0.05) def grep(lines,pattern): for line in lines: line=line.decode('utf-8') if pattern in line: yield line lines=grep(tail('access.log'),'404') for line in lines: print(line) #了解知识点:yield表达式形式的用法 def eater(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list#food=yield='一盆骨头' food_list.append(food) print('%s start to eat %s' %(name,food)) e=eater('xglv') #首先初始化: print(e.send(None)) # next(e) 初始化时遇到yied后会先返回值,然后再停止等待接收值 #然后e.send:1 从暂停的位置将值传给yield 2、与next一样 print(e.send('肉')) print(e.send('肉'))
三、面向过程编程
#grep -rl 'python' /etc #补充:os.walk 接收目录or.walk(r"D:\video") ,返回结果为一个生成器,next的结果为一个3个元素的元组,第一个元素为父目录,第二个元素为第一个元素下的所有目录,第三个元素为第一个元素下的所有文件。 import os g=os.walk(r'./a') print(next(g)) #('./a', ['b1', 'b2', 'b3'], ['a.txt']) print(next(g)) #('./a/b1', ['c1'], ['b1.txt']) print(next(g)) #('./a/b1/c1', [], ['c1.txt']) print(next(g)) #('./a/b2', [], ['b2.txt']) for pardir,_,files in g: for file in files: abs_path=r'%s/%s' %(pardir,file) print(abs_path) #./a/b3/b3.txt #./a/b3/c3/c3.txt #分析一: # #第一步:拿到一个文件夹下所有的文件的绝对路径 # import os # # def search(target): #r'D:\video\python20期\day4\a' # while True: # filepath=yield #fllepath=yield=r'D:\video\python20期\day4\a' # g=os.walk(filepath) # for pardir, _, files in g: # for file in files: # abs_path = r'%s\%s' % (pardir, file) # # print(abs_path) # target.send(abs_path) # # # search(r'D:\video\python20期\day4\a') # # search(r'D:\video\python20期\day4') # # # #第二步:打开文件拿到文件对象f # def opener(): # while True: # abs_path=yield # print('opener func--->',abs_path) # # # target=opener() # next(target) #target.send('xxxx') # # g=search(target) # next(g) # g.send(r'D:\video\python20期\day4\a') #分析二: # 第一步:拿到一个文件夹下所有的文件的绝对路径 import os def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner @init def search(target): # r'D:\video\python20期\day4\a' while True: filepath = yield g = os.walk(filepath) for pardir, _, files in g: for file in files: abs_path = r'%s/%s' % (pardir, file) #把abs_path传给下一个阶段 target.send(abs_path) # 第二步:打开文件拿到文件对象f @init def opener(target): while True: abs_path = yield with open(abs_path,'rb') as f: #把(abs_path,f)传给下一个阶段 target.send((abs_path,f)) #第三步:读取f的每一行内容 @init def cat(target): while True: abs_path,f=yield for line in f: #把(abs_path,line)传给下一个阶段 res=target.send((abs_path,line)) #满足某种条件,break掉for循环 if res: break #第四步:判断'python' in line @init def grep(target,pattern): pattern = pattern.encode('utf-8') res=False while True: abs_path,line=yield res res=False if pattern in line: #把abs_path传给下一个阶段 res=True target.send(abs_path) #第五步:打印文件路径 @init def printer(): while True: abs_path=yield print('<%s>' %abs_path) g=search(opener(cat(grep(printer(),'python')))) #'python' in b'xxxxx' g.send("./a") #<./a/a.txt> #<./a/b1/c1/c1.txt> #面向过程编程:核心是过程二字,过程指的就是解决问题的步骤,即先干什么后干什么。。。。 #基于该思路编写程序就好比设计一条流水线,是一种机械式的思维方式 #优点:复杂的问题流程化、进而简单化 #缺点:可扩展性差
四、三元表达式
def my_max(x,y): if x >= y: return x else: return y x=10 y=20 # res=x if x >= y else y # print(res) name=input('>>: ').strip() res='NB' if name == 'xglv' else '哈哈' print(res)
五、列表推导是和生成器表达式
#1 列表推导式 l=[] for i in range(1,11): res='egg'+str(i) l.append(res) print(l) l=['egg'+str(i) for i in range(1,11)] print(l) l1=['egg'+str(i) for i in range(1,11) if i >= 6] print(l1) l1=[] for i in range(1,11): if i >= 6: l1.append('egg'+str(i)) #2 生成器表达式 g=('egg'+str(i) for i in range(0,100)) print(g) print(next(g)) print(next(g)) print(next(g)) #练习 names=['egon','alex_sb','wupeiqi','yuanhao'] names=[name.upper() for name in names] print(names) sbs=[name for name in names if name.endswith('sb')] print(sbs) obj=list('abcdef') print(obj) # print(max([1,2,3,4,5])) # g=(i for i in range(10)) # print(max(g)) # # print(max(g)) with open('a.txt','r',encoding='utf-8') as f: # l=[] # for line in f: # # print(len(line)) # l.append(len(line)) g=(len(line) for line in f) #max接收可迭代对象 res=max(g) print(res) # list 也是遵循迭代器原则的 # print(max(len(line) for line in f)) with open('a.txt', 'r', encoding='utf-8') as f: print(sum(len(line) for line in f)) #print(sum((len(line) for line in f)))
六、递归
#递归调用:在调用一个函数的过程中,直接或者间接又调用该函数本身,称之为递归调用 #递归必备的两个阶段:1、递推 2、回溯 import sys print(sys.getrecursionlimit()) #查看递归层数限制 默认是1000 sys.setrecursionlimit(2000) #修改递归层数限制 print(sys.getrecursionlimit()) # def func(n): # print('---->',n) # func(n+1) # # func(0) # def bar(): # print('from bar') # func() # # def func(): # print('from func') # bar() # # func() # age(5) = age(4) + 2 # age(4) = age(3) + 2 # age(3) = age(2) + 2 # age(2) = age(1) + 2 # # age(1) = 18 # age(n)=age(n-1)+2 # n > 1 # age(1) = 18 #n = 1 def age(n): if n == 1: return 18 return age(n-1) + 2 res=age(5) print(res) l=[1,[2,[3,[4,[5,[6,[7,]]]]]]] def func(l): for item in l: if type(item) is list: func(item) else: print(item) #了解的知识点 二分法 l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def binary_search(l,num): print(l) if len(l) == 0: print('not exists') return mid_index=len(l) // 2 if num > l[mid_index]: #往右找 binary_search(l[mid_index+1:],num) elif num < l[mid_index]: #往左找 binary_search(l[0:mid_index],num) else: print('find it') # binary_search(l,301) binary_search(l,302)
七、匿名函数
# def func(): #func=内存地址 # print('from func') # # func() # func() # 内存地址 # def my_sum(x,y): # return x+y print(lambda x,y:x+y) #<function <lambda> at 0x102a47510> print((lambda x,y:x+y)(1,2)) #3 func=lambda x,y:x+y # print(func) print(func(1,2)) #3 #匿名函数与其他函数的配合使用 #max,min,sorted,map,reduce,filter salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } print(max(salaries)) s='hello' l=[1,2,3] g=zip(s,l) #zip(拉链) 接收多可可迭代对象 执行后zip会把所以一致的元素放到一个元组里,作为返回元组的一个元素,若有多余的舍弃 # print(g) print(list(g)) g=zip(salaries.values(),salaries.keys()) # print(list(g)) print(max(g)) def func(k): return salaries[k] #max 函数接收3个参数,第一个参数为迭代器对象,第二个参数为key 该key的意思为max已什么比较(一般为一个函数,该函数接收的值为第一个参数next()的返回值函数的返回值作为比较的依据) print(max(salaries,key=func)) #key=func('egon') print(max(salaries,key=lambda k:salaries[k])) #key=func('egon') print(min(salaries,key=lambda k:salaries[k])) #key=func('egon') #sorted #sorted 函数接收3个参数,第一个参数为迭代器对象,第二个参数为key 该key的意思为已什为排序依据(一般为一个函数,该函数接收的值为第一个参数next()的返回值函数的返回值作为排序的依据) salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } print(sorted(salaries,key=lambda k:salaries[k])) #['yuanhao', 'egon', 'wupeiqi', 'alex'] print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #['alex', 'wupeiqi', 'egon', 'yuanhao'] with open("a.txt","r",encoding="utf-8") as f: res = sorted(f,key = lambda line:len(line)) print(res) #['1\n', '12', '345\n', '123234\n'] #map,reduce,filter names=['alex','wupeiqi','yuanhao'] l=[] for name in names: res='%s_haha' %name l.append(res) print(l) #['alex_haha', 'wupeiqi_haha', 'yuanhao_haha'] #map 接收2个参数,第一个为函数,第二个为可迭代对象, 第一个函数的参数为第二参数next()的返回值, map返回一个生成器(函数处理的结果) g=map(lambda name:'%s_haha' %name,names) # print(g) print(list(g)) #['alex_haha', 'wupeiqi_haha', 'yuanhao_haha'] #filer(过滤) 接收2个参数,第一个参数为函数(过滤规则) ,第二个参数为一个可迭代对象 第一个函数的参数为第二参数next()的返回值,若函数的条件为Ture则返回该值 filer返回一个生成器(函数处理的结果) names=['alex_hah','wupeiqi_hah','yuanhao_hah','egon'] g=filter(lambda x:x.endswith('hah'),names) print(g) print(list(g)) #['alex_hah', 'wupeiqi_hah', 'yuanhao_hah'] from functools import reduce #reduce(合并) 接收3个参数 第一个参数为函数,第二个参数为可迭代对象,第三个参数为起始值,第一个函数接收两个参数,(为上一次执行的结果(第一次为起始值,若没有函数两参数为第二个参数执行两次next()的值)和第二个参数的next()的值,) print(reduce(lambda x,y:x+y,range(1,101),100)) #5150
八、内置函数
了解 print(abs(-1)) #1 print(all([1,'a','b',0])) #False print(all([])) #True print(any([None,False,0,1])) #True print(any([])) #False print(bin(11)) #0b1011 print(hex(11)) #0xb print(oct(11)) #0o13 print('xxx'.encode('utf-8')) #b'xxx' print(bytes('xxx',encoding='utf-8')) #b'xxx' print(callable(max)) #True print(chr(65)) #A # print(chr(90)) # print(chr(39)) print(ord('A')) #65 import os print(dir(os)) #['CLD_CONTINUED', 'CLD_DUMPED', 'CLD_EXITED', 'CLD_TRAPPED', 'DirEntry', 'EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', 'EX_NOHOST', 'EX_NOINPUT', 'EX_NOPERM', 'EX_NOUSER', 'EX_OK', 'EX_OSERR', 'EX_OSFILE', 'EX_PROTOCOL', 'EX_SOFTWARE', 'EX_TEMPFAIL', 'EX_UNAVAILABLE', 'EX_USAGE', 'F_LOCK', 'F_OK', 'F_TEST', 'F_TLOCK', 'F_ULOCK', 'MutableMapping', 'NGROUPS_MAX', 'O_ACCMODE', 'O_APPEND', 'O_ASYNC', 'O_CREAT', 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_EXLOCK', 'O_NDELAY', 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_RDONLY', 'O_RDWR', 'O_SHLOCK', 'O_SYNC', 'O_TRUNC', 'O_WRONLY', 'PRIO_PGRP', 'PRIO_PROCESS', 'PRIO_USER', 'P_ALL', 'P_NOWAIT', 'P_NOWAITO', 'P_PGID', 'P_PID', 'P_WAIT', 'PathLike', 'RTLD_GLOBAL', 'RTLD_LAZY', 'RTLD_LOCAL', 'RTLD_NODELETE', 'RTLD_NOLOAD', 'RTLD_NOW', 'R_OK', 'SCHED_FIFO', 'SCHED_OTHER', 'SCHED_RR', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'ST_NOSUID', 'ST_RDONLY', 'TMP_MAX', 'WCONTINUED', 'WCOREDUMP', 'WEXITED', 'WEXITSTATUS', 'WIFCONTINUED', 'WIFEXITED', 'WIFSIGNALED', 'WIFSTOPPED', 'WNOHANG', 'WNOWAIT', 'WSTOPPED', 'WSTOPSIG', 'WTERMSIG', 'WUNTRACED', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_fspath', '_get_exports_list', '_putenv', '_spawnvef', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chflags', 'chmod', 'chown', 'chroot', 'close', 'closerange', 'confstr', 'confstr_names', 'cpu_count', 'ctermid', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'environb', 'errno', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fchdir', 'fchmod', 'fchown', 'fdopen', 'fork', 'forkpty', 'fpathconf', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fstatvfs', 'fsync', 'ftruncate', 'get_blocking', 'get_exec_path', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getegid', 'getenv', 'getenvb', 'geteuid', 'getgid', 'getgrouplist', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getpid', 'getppid', 'getpriority', 'getsid', 'getuid', 'initgroups', 'isatty', 'kill', 'killpg', 'lchflags', 'lchmod', 'lchown', 'linesep', 'link', 'listdir', 'lockf', 'lseek', 'lstat', 'major', 'makedev', 'makedirs', 'minor', 'mkdir', 'mkfifo', 'mknod', 'name', 'nice', 'open', 'openpty', 'pardir', 'path', 'pathconf', 'pathconf_names', 'pathsep', 'pipe', 'popen', 'pread', 'putenv', 'pwrite', 'read', 'readlink', 'readv', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sched_get_priority_max', 'sched_get_priority_min', 'sched_yield', 'sendfile', 'sep', 'set_blocking', 'set_inheritable', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp', 'setpriority', 'setregid', 'setreuid', 'setsid', 'setuid', 'spawnl', 'spawnle', 'spawnlp', 'spawnlpe', 'spawnv', 'spawnve', 'spawnvp', 'spawnvpe', 'st', 'stat', 'stat_float_times', 'stat_result', 'statvfs', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sync', 'sys', 'sysconf', 'sysconf_names', 'system', 'tcgetpgrp', 'tcsetpgrp', 'terminal_size', 'times', 'times_result', 'truncate', 'ttyname', 'umask', 'uname', 'uname_result', 'unlink', 'unsetenv', 'urandom', 'utime', 'wait', 'wait3', 'wait4', 'waitpid', 'walk', 'write', 'writev'] s=set({1,2,3}) s.add(4) print(s) #{1, 2, 3, 4} s=frozenset({1,2,3}) #不可变集合 print(hash('xxx')) #-8056993023807955300 #reversed 接收可迭代对象 l=[1,2,'a',4] print(list(reversed(l))) s=slice(1,5,2) l=['a','b','c','d','e'] # print(l[1:5:2]) # print(l[1:5:2]) print(l[s]) #['b', 'd'] #print(vars() is locals()) #True #面向对象 # classmethod # staticmethod # property # # # hasattr # getattr # setattr # delattr # # isinstance # issubclass # # object # # super # obj.__dict__() #vars(obj) #__import__ 通过字符串的形式导入模块 choice=input('>>: ') print(choice,type(choice)) # import 'time' m=__import__(choice) m.sleep(10) #掌握: #divmod (把计算的商和余返回) print(divmod(10011,25)) #(400, 11) #enumerate l=['a','b','c'] for i in l: print(l.index(i),i,) #0 a #1 b #2 c for i,v in enumerate(l): print(i,v) #0 a #1 b #2 c #eval:字符串中的表达式提取出来 有返回值 res=eval('[1,2,3]') print(res,type(res)) #[1, 2, 3] <class 'list'> res=exec('[1,2,3]') #为返回值 print(res) #None #pow 接收3个值 res=pow(2,3,3) # (2 ** 3 )%3 print(res) #2 #round 四舍五入 print(round(3.5))