day4:迭代器、生成器、面向过程编程、三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

一、迭代器

1、迭代器概念:

迭代器就是迭代的工具,迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

2、什么是可迭代对象?

可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__

 1 dic={
 2     'a':1,
 3     'b':2,
 4     'c':3
 5 }
 6 iter_dic=dic.__iter__()
 7 print(iter_dic.__iter__() is iter_dic)
 8 print(iter_dic.__next__())
 9 print(iter_dic.__next__())
10 print(iter_dic.__next__())
View Code
1 iter_dic=dic.__iter__()
2 while 1:
3     try:
4         k=next(iter_dic)
5         print(dic[k])
6     except StopIteration:
7         break
View Code

3、for循环的工作原理

#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环

4、迭代器的优缺点

#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退

二、生成器

只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码

def func():
    print('====>first')
    yield 1
    print('====>second')
    yield 2
    print('====>third')
    yield 3
    print('====>end')

g=func()
print(g) #<generator object func at 0x0000000002184360> 
View Code

生成器就是迭代器

1、练习

1)自定义函数模拟range(1,7,2)

2)模拟管道,实现功能:tail -f access.log | grep '404'

1.
def range_test(x,y,z=1):
    while x <= y:
        yield x
        #print(x)
        x+=z

g=range_test(1,2)
print(next(g))
print(next(g))
2.
import time
def tail(file):
    with open(file,'rb') as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)
def grep(lines,partten):
    for line in lines:
        line=line.decode('utf-8')
        if partten in line:
            yield line
for line in grep(tail('access.log'),'404'):
    print(line)
练习题

三、协成函数

#yield关键字的另外一种使用形式:表达式形式的yield
def eater(name):
    print('%s 准备开始吃饭啦' %name)
    food_list=[]
    while True:
        food=yield food_list
        print('%s 吃了 %s' % (name,food))
        food_list.append(food)

g=eater('egon')
g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)
g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('烧素鸭')
g.close()
g.send('烧素鹅')
g.send('烧鹿尾')
View Code
def init(func):
    def inner(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return inner

@init
def eater(name):
    print('%s begin eat!!!' %name)
    food_list=[]
    while True:
        food=yield food_list
        print('%s eat %s' %(name,food_list))
        food_list.append(food)
g=eater('egon')
#g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)

g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('烧素鸭')
g.send('烧素鹅')
g.send('烧鹿尾')
1.编写装饰器,实现初始化协程函数的功能
import os
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

@init
def search(target):
    while True:
        filepath=yield
        g=os.walk(filepath)
        for dirname,_,files in g:
            for file in files:
                abs_path=r'%s\%s' %(dirname,file)
                target.send(abs_path)
@init
def opener(target):
    while True:
        abs_path=yield
        with open(abs_path,'rb') as f:
            target.send((f,abs_path))
@init
def cat(target):
    while True:
        f,abs_path=yield
        for line in f:
            res=target.send((line,abs_path))
            if res:
                break
@init
def grep(pattern,target):
    tag=False
    while True:
        line,abs_path=yield tag
        tag=False
        if pattern.encode('utf-8') in line:
            target.send(abs_path)
            tag=True
@init
def printer():
    while True:
        abs_path=yield
        print(abs_path)


g=search(opener(cat(grep('你好',printer()))))
# g.send(r'E:\CMS\aaa\db')
g=search(opener(cat(grep('python',printer()))))
g.send(r'E:\CMS\aaa\db')
2、实现功能:grep -rl 'python' /etc

yield总结

#1、把函数做成迭代器
#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

 四、三元表达式、列表推导式、生成器表达式

name=input('>>: ')
res='sb' if name=='alex' else 'nb'
print(res)
三元表达式例子
egg_list=['egg_%s' %i for i in range(10)]
print(egg_list)
列表推导式

语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN

]

egg_list=('egg_%s' %i for i in range(10))
print(egg_list)
print(next(egg_list))
print(next(egg_list))
生成器表达式

#1、把列表推导式的[]换成()就是生成器表达式

#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性

#3、优点:省内存,一次只产生一个值在内存中

list(chicken) #因chicken可迭代,因而可以转成列表
['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]

4.1 练习题

1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写

names=['egon','alex_sb','wupeiqi','yuanhao']
names=[i.upper() for i in names]
print(names)
View Code

2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度

names=['egon','alex_sb','wupeiqi','yuanhao']
names=[len(i) for i in names if not i.endswith('sb')]
print(names)
View Code

3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)

with open('access.log','r',encoding='utf-8') as f:
    a=[len(i) for i in f]
    print(a)
    print(max(a))
View Code

4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

with open('access.log', encoding='utf-8') as f:
    print(sum(len(i) for i in f))
View Code

5、思考题

with open('a.txt') as f:
    g=(len(line) for line in f)
print(sum(g)) #为何报错?

因为print在with代码块之外,也就是相当于文件已经关闭,所以sum函数没有办法做运算

6、文件shopping.txt内容如下

mac,20000,3
lenovo,3000,10
tesla,1000000,10
chicken,200,1

求总共花了多少钱?

打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]

求单价大于10000的商品信息,格式同上
with open('shopping.txt') as f:
    info=[i.split(',')for i in f]
    cost=sum(int(x)*int(y) for _,x,y in info)
    print(cost)

with open('shopping.txt') as f:
    info=[{
        'name':line.split(',')[0],
        'price':line.split(',')[1],
        'count':line.split(',')[2]
    } for line in f]

with open('shopping.txt',encoding='utf-8') as f:
    info=[{
        'name': line.split()[0],
        'price': float(line.split()[1]),
        'count': int(line.split()[2]),
    } for line in f if float(line.split()[1]) > 10000]
    print(info)
View Code

 

---恢复内容结束---

一、迭代器

1、迭代器概念:

迭代器就是迭代的工具,迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

2、什么是可迭代对象?

可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__

 1 dic={
 2     'a':1,
 3     'b':2,
 4     'c':3
 5 }
 6 iter_dic=dic.__iter__()
 7 print(iter_dic.__iter__() is iter_dic)
 8 print(iter_dic.__next__())
 9 print(iter_dic.__next__())
10 print(iter_dic.__next__())
View Code
1 iter_dic=dic.__iter__()
2 while 1:
3     try:
4         k=next(iter_dic)
5         print(dic[k])
6     except StopIteration:
7         break
View Code

3、for循环的工作原理

#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环

4、迭代器的优缺点

#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退

二、生成器

只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码

def func():
    print('====>first')
    yield 1
    print('====>second')
    yield 2
    print('====>third')
    yield 3
    print('====>end')

g=func()
print(g) #<generator object func at 0x0000000002184360> 
View Code

生成器就是迭代器

1、练习

1)自定义函数模拟range(1,7,2)

2)模拟管道,实现功能:tail -f access.log | grep '404'

1.
def range_test(x,y,z=1):
    while x <= y:
        yield x
        #print(x)
        x+=z

g=range_test(1,2)
print(next(g))
print(next(g))
2.
import time
def tail(file):
    with open(file,'rb') as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)
def grep(lines,partten):
    for line in lines:
        line=line.decode('utf-8')
        if partten in line:
            yield line
for line in grep(tail('access.log'),'404'):
    print(line)
练习题

三、协成函数

#yield关键字的另外一种使用形式:表达式形式的yield
def eater(name):
    print('%s 准备开始吃饭啦' %name)
    food_list=[]
    while True:
        food=yield food_list
        print('%s 吃了 %s' % (name,food))
        food_list.append(food)

g=eater('egon')
g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)
g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('烧素鸭')
g.close()
g.send('烧素鹅')
g.send('烧鹿尾')
View Code
def init(func):
    def inner(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return inner

@init
def eater(name):
    print('%s begin eat!!!' %name)
    food_list=[]
    while True:
        food=yield food_list
        print('%s eat %s' %(name,food_list))
        food_list.append(food)
g=eater('egon')
#g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)

g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('烧素鸭')
g.send('烧素鹅')
g.send('烧鹿尾')
1.编写装饰器,实现初始化协程函数的功能
import os
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

@init
def search(target):
    while True:
        filepath=yield
        g=os.walk(filepath)
        for dirname,_,files in g:
            for file in files:
                abs_path=r'%s\%s' %(dirname,file)
                target.send(abs_path)
@init
def opener(target):
    while True:
        abs_path=yield
        with open(abs_path,'rb') as f:
            target.send((f,abs_path))
@init
def cat(target):
    while True:
        f,abs_path=yield
        for line in f:
            res=target.send((line,abs_path))
            if res:
                break
@init
def grep(pattern,target):
    tag=False
    while True:
        line,abs_path=yield tag
        tag=False
        if pattern.encode('utf-8') in line:
            target.send(abs_path)
            tag=True
@init
def printer():
    while True:
        abs_path=yield
        print(abs_path)


g=search(opener(cat(grep('你好',printer()))))
# g.send(r'E:\CMS\aaa\db')
g=search(opener(cat(grep('python',printer()))))
g.send(r'E:\CMS\aaa\db')
2、实现功能:grep -rl 'python' /etc

yield总结

#1、把函数做成迭代器
#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

 四、三元表达式、列表推导式、生成器表达式

name=input('>>: ')
res='sb' if name=='alex' else 'nb'
print(res)
三元表达式例子
egg_list=['egg_%s' %i for i in range(10)]
print(egg_list)
列表推导式

语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN

]

egg_list=('egg_%s' %i for i in range(10))
print(egg_list)
print(next(egg_list))
print(next(egg_list))
生成器表达式

#1、把列表推导式的[]换成()就是生成器表达式

#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性

#3、优点:省内存,一次只产生一个值在内存中

list(chicken) #因chicken可迭代,因而可以转成列表
['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]

4.1 练习题

1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写

names=['egon','alex_sb','wupeiqi','yuanhao']
names=[i.upper() for i in names]
print(names)
View Code

2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度

names=['egon','alex_sb','wupeiqi','yuanhao']
names=[len(i) for i in names if not i.endswith('sb')]
print(names)
View Code

3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)

with open('access.log','r',encoding='utf-8') as f:
    a=[len(i) for i in f]
    print(a)
    print(max(a))
View Code

4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

with open('access.log', encoding='utf-8') as f:
    print(sum(len(i) for i in f))
View Code

5、思考题

with open('a.txt') as f:
    g=(len(line) for line in f)
print(sum(g)) #为何报错?

因为print在with代码块之外,也就是相当于文件已经关闭,所以sum函数没有办法做运算

6、文件shopping.txt内容如下

mac,20000,3
lenovo,3000,10
tesla,1000000,10
chicken,200,1

求总共花了多少钱?

打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]

求单价大于10000的商品信息,格式同上
with open('shopping.txt') as f:
    info=[i.split(',')for i in f]
    cost=sum(int(x)*int(y) for _,x,y in info)
    print(cost)

with open('shopping.txt') as f:
    info=[{
        'name':line.split(',')[0],
        'price':line.split(',')[1],
        'count':line.split(',')[2]
    } for line in f]

with open('shopping.txt',encoding='utf-8') as f:
    info=[{
        'name': line.split()[0],
        'price': float(line.split()[1]),
        'count': int(line.split()[2]),
    } for line in f if float(line.split()[1]) > 10000]
    print(info)
View Code

 五、递归与二分法

1、递归调用的定义

#递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用

2、递归示例

#图解。。。
# salary(5)=salary(4)+300
# salary(4)=salary(3)+300
# salary(3)=salary(2)+300
# salary(2)=salary(1)+300
# salary(1)=100
#
# salary(n)=salary(n-1)+300     n>1
# salary(1) =100                n=1

def salary(n):
    if n == 1:
        return 100
    return salary(n-1)+300

print(salary(5))

3、修改递归最大深度

import sys
sys.getrecursionlimit()
sys.setrecursionlimit(2000)
n=1
def test():
    global n
    print(n)
    n+=1
    test()

test()

#虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归

4、二分法

l=[1,2,10,30,33,99,101,200,301,402]
print(l)
a=int(input('>>: '))
while True:
    mid=len(l)//2
    if a>l[mid]:
        l=l[mid+1:]
    elif a<l[mid]:
        l=l[:mid]
    else:
        print(l.index(a))
        break
简陋版示例
复制代码
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表

def search(num,l):
    print(l)
    if len(l) > 0:
        mid=len(l)//2
        if num > l[mid]:
            #in the right
            l=l[mid+1:]
        elif num < l[mid]:
            #in the left
            l=l[:mid]
        else:
            print('find it')
            return
        search(num,l)
    else:
        #如果值不存在,则列表切为空
        print('not exists')
        return
search(100,l)
egon博客示例

 

 

 

posted @ 2018-01-05 17:05  培天王  阅读(64)  评论(0)    收藏  举报