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))

 

posted @ 2017-12-25 09:29  xglv  阅读(270)  评论(0编辑  收藏  举报